home *** CD-ROM | disk | FTP | other *** search
/ Windows Undocumented File Formats / Windows Undocumented File Formats.img / CHAP7 / RES2RC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-21  |  91.6 KB  |  3,260 lines

  1. /**********************************************************************
  2.  *
  3.  * PROGRAM: RES2RC.C
  4.  *
  5.  * PURPOSE: Converts a .RES file to an .RC file
  6.  *
  7.  * Copyright 1997, Mike Wallace and Pete Davis
  8.  *
  9.  * Chapter 7, Resource (.RES) File Format, from Undocumented Windows
  10.  * File Formats, published by R&D Books, an imprint of Miller Freeman, Inc.
  11.  *
  12.  **********************************************************************/
  13.  
  14. #include "restypes.h"
  15.  
  16. /***************************************************
  17.    Read a byte from infile
  18. ****************************************************/
  19. BYTE get_byte(FILE *infile) {
  20.  
  21.     BYTE ch;
  22.  
  23.     fread(&ch, sizeof(BYTE), 1, infile);
  24.     return(ch);
  25.  
  26. } /* get_byte - end */
  27.  
  28.  
  29. /***************************************************
  30.    Read a word from infile
  31. ****************************************************/
  32. WORD get_word(FILE *infile) {
  33.  
  34.     WORD num;
  35.  
  36.     fread(&num, sizeof(WORD), 1, infile);
  37.     return(num);
  38.  
  39. } /* get_word - end */
  40.  
  41.  
  42. /***************************************************
  43.    Write out an integer to outfile
  44. ****************************************************/
  45. void write_number(int num, FILE *outfile) {
  46.  
  47.     fprintf( outfile, "%d ", num);
  48.  
  49. } /* write_number - end */
  50.  
  51.  
  52. /***************************************************
  53.    Write out a word (unsigned short integer) to outfile
  54. ****************************************************/
  55. void write_word(WORD num, FILE *outfile) {
  56.  
  57.     fprintf( outfile, "%hu", num);
  58.  
  59. } /* write_word - end */
  60.  
  61.  
  62. /***************************************************
  63.    Write out a dword (unsigned long) to outfile
  64. ****************************************************/
  65. void write_dword(DWORD num, FILE *outfile) {
  66.  
  67.     fprintf( outfile, "%lu", num);
  68.  
  69. } /* write_dword - end */
  70.  
  71.  
  72. /***************************************************
  73.    Write out a character to outfile
  74. ****************************************************/
  75. void write_char(char ch, FILE *outfile) {
  76.  
  77.    /* if the character is null, write out the string "\0" */
  78.    if (ch == '\0')
  79.       fprintf( outfile, "\\0");
  80.    else
  81.       fprintf( outfile, "%c", ch);
  82.  
  83. } /* write_char - end */
  84.  
  85.  
  86. /***************************************************
  87.    Write out an unsigned character to outfile
  88. ****************************************************/
  89. void write_byte(BYTE ch, FILE *outfile) {
  90.  
  91.     fputc( ch, outfile);
  92.  
  93. } /* write_byte - end */
  94.  
  95.  
  96. /***************************************************
  97.    Write out a string to outfile, then add a newline
  98. ****************************************************/
  99. void writeline(char *string, FILE *outfile) {
  100.  
  101.    if(strlen(string))
  102.        fputs( string, outfile);
  103.  
  104.    fputc( CR, outfile);
  105.    fputc( NL, outfile);
  106.  
  107. } /* writeline - end */
  108.  
  109.  
  110. /***************************************************
  111.    Write out a string to outfile
  112. ****************************************************/
  113. void writestring(char *string, FILE *outfile) {
  114.  
  115.    if(strlen(string))
  116.        fputs( string, outfile);
  117.  
  118. } /* writestring - end */
  119.  
  120.  
  121. /***************************************************
  122.    Increase the INDENT variable value by INDENT_SPACES
  123. ****************************************************/
  124. void increase_indent( void ) {
  125.  
  126.     INDENT += INDENT_SPACES;
  127.  
  128. } /* increase_indent - end */
  129.  
  130.  
  131. /***************************************************
  132.    Decrease the INDENT variable value by INDENT_SPACES
  133. ****************************************************/
  134. void decrease_indent( void ) {
  135.  
  136.     if((INDENT -= INDENT_SPACES) < 0)
  137.        INDENT = 0;
  138.  
  139. } /* decrease_indent - end */
  140.  
  141.  
  142. /***************************************************
  143.    Write out INDENT spaces to outfile
  144. ****************************************************/
  145. void write_indent(FILE *outfile) {
  146.  
  147.     int n;
  148.  
  149.     for(n = INDENT; (n); --n)
  150.        write_char(' ', outfile);
  151.  
  152. } /* write_indent - end */
  153.  
  154.  
  155. /***************************************************
  156.    If the last stringtable wasn't closed, do so now.   
  157. ****************************************************/
  158. void finish_off_stringtable(FILE *outfile) {
  159.  
  160.    if (StringCount)
  161.       writeline("}", outfile);
  162.  
  163. } /* finish_off_stringtable - end */
  164.  
  165.  
  166. /***************************************************
  167.    Get name of custom resource
  168. ****************************************************/
  169. void get_custom_type( BYTE ch, FILE *infile, FILE *outfile) {
  170.  
  171.    while(ch != 0x00) {
  172.       write_char(ch, outfile);
  173.       ch = get_byte(infile);
  174.    }
  175.  
  176. } /* get_custom_type - end */
  177.  
  178.  
  179. /***************************************************
  180.    Get the resource name from the .res file (infile)
  181. ****************************************************/
  182. DWORD write_item_text(FILE *infile, FILE *outfile) {
  183.  
  184.    BYTE  ch;
  185.    DWORD length;
  186.  
  187.    ch = get_byte( infile );
  188.    if(ch == 0x00)
  189.       return(1);
  190.    writestring("\"", outfile);
  191.    length = 1;
  192.    while(ch != 0x00) {
  193.       ++length;
  194.       write_char(ch, outfile);
  195.       ch = get_byte( infile );
  196.    }
  197.    writestring("\"", outfile);
  198.    return(length);
  199.  
  200. } /* write_item_text - end */
  201.  
  202.  
  203. /***************************************************
  204.    Returns the first new filename of the form
  205.    <prefix>#.<suffix>
  206. ****************************************************/
  207. char *get_data_filename(char *prefix, char *suffix) {
  208.  
  209.    FILE *fp;
  210.    WORD number;
  211.    char fname[13];
  212.    char fname_start[3];
  213.    char fname_end[5];
  214.    int  name_length;
  215.  
  216.    /* form the prefix to the new filename */
  217.    name_length = (strlen(prefix) > 2) ? 2 : strlen(prefix);
  218.    strncpy(fname_start, prefix, name_length);
  219.    fname_start[name_length] = '\0';
  220.  
  221.    /* form the suffix to the new filename */
  222.    fname_end[0] = '.';
  223.    name_length = (strlen(suffix) > 3) ? 3 : strlen(suffix);
  224.    strncat( fname_end, suffix, name_length);
  225.    fname_end[name_length + 1] = '\0';
  226.  
  227.    /* Keep forming new filenames until we get to one we can't open */
  228.    number = 0;
  229.    sprintf( fname, "%s%u%s", fname_start, number, fname_end);
  230.    while((number < 1000) && ((fp = fopen( fname, "r")) != NULL)) {
  231.       fclose(fp);
  232.       ++number;
  233.       sprintf( fname, "%s%u%s", fname_start, number, fname_end);
  234.    }
  235.  
  236.    if(number == 1000)
  237.       fname[0] = '\0';
  238.  
  239.    return(fname);
  240.  
  241. } /* get_data_filename - end */
  242.  
  243.  
  244. /***************************************************
  245.    Write out reslen bytes of data to datafile
  246. ****************************************************/
  247. void write_data( FILE *infile, FILE *datafile, DWORD reslen ) {
  248.  
  249.    BYTE ch;
  250.  
  251.    ch = get_byte(infile);
  252.    while(reslen) {
  253.       fputc( ch, datafile);
  254.       if(--reslen)
  255.          ch = get_byte(infile);
  256.    }
  257.    
  258. } /* write_data - end */
  259.  
  260.  
  261. /***************************************************
  262.    Retrieves the length of the resource from the .res file
  263. ****************************************************/
  264. DWORD get_resource_length(FILE *infile) {
  265.  
  266.    DWORD reslen;
  267.  
  268.    fread(&reslen, sizeof(DWORD), 1, infile);
  269.  
  270.    return(reslen);
  271.  
  272. } /* get_resource_length - end */
  273.  
  274.  
  275. /***************************************************
  276.    Get the resource name from the .res file (infile)
  277. ****************************************************/
  278. void get_resource_name(FILE *infile) {
  279.  
  280.    int resname;
  281.    BYTE ch;
  282.  
  283.    ch = get_byte(infile);
  284.    if(ch == 0xFF) {
  285.        fread(&resname, sizeof(int), 1, infile);
  286.    }
  287.    else {
  288.       ch = get_byte(infile);
  289.       while((!feof(infile)) && (ch != 0x00)) {
  290.          ch = get_byte(infile);
  291.       }
  292.    }
  293.  
  294. } /* get_resource_name - end */
  295.  
  296.  
  297. /***************************************************
  298.    Get the version name from the .res file (infile)
  299. ****************************************************/
  300. void get_version_name(FILE *infile) {
  301.  
  302.    int  count=1; /* record number of chars read */
  303.    BYTE ch;
  304.  
  305.    ch = get_byte(infile);
  306.    while((!feof(infile)) && (ch != 0x00)) {
  307.       ++count;
  308.       ch = get_byte(infile);
  309.    }
  310.  
  311.    /* Ensure number of characters read is a multiple of 4.    */
  312.    /* According to the MS documentation, this is the format.  */
  313.    /* See "MS Windows 3.1 Programmer's Reference" Vol.4, p.99 */
  314.    count = count % 4;
  315.    count = (count > 0) ? (4 - count) : 0;
  316.    while ((!feof(infile)) && (count > 0)) {
  317.       ch = get_byte(infile);
  318.       --count;
  319.    }
  320.  
  321. } /* get_version_name - end */
  322.  
  323.  
  324. /***************************************************
  325.    Get the resource number from the .res file (infile)
  326. ****************************************************/
  327. WORD get_resource_number(FILE *infile) {
  328.  
  329.    WORD resname = 0;
  330.    BYTE ch;
  331.  
  332.    ch = get_byte(infile);
  333.    if(ch == 0xFF) {
  334.        resname = get_word( infile );
  335.    }
  336.    else {
  337.       ch = get_byte(infile);
  338.       while((!feof(infile)) && (ch != 0x00)) {
  339.          ch = get_byte(infile);
  340.       }
  341.    }
  342.  
  343.    return(resname);
  344.  
  345. } /* get_resource_number - end */
  346.  
  347.  
  348. /***************************************************
  349.    Get the resource name from the .res file (infile)
  350. ****************************************************/
  351. void write_resource_name(FILE *infile, FILE *outfile) {
  352.  
  353.    int resname;
  354.    BYTE ch;
  355.  
  356.    writeline( "", outfile);
  357.  
  358.    ch = get_byte(infile);
  359.    if(ch == 0xFF) {
  360.        fread(&resname, sizeof(int), 1, infile);
  361.        write_number(resname, outfile);
  362.    }
  363.    else {
  364.       write_char(ch, outfile);
  365.       ch = get_byte(infile);
  366.       while((!feof(infile)) && (ch != 0x00)) {
  367.          write_char(ch, outfile);
  368.          ch = get_byte(infile);
  369.       }
  370.    }
  371.  
  372. } /* write_resource_name - end */
  373.  
  374.  
  375. /***************************************************
  376.    Get the version number from the .res file (infile)
  377. ****************************************************/
  378. void write_version_number(FILE *infile, FILE *outfile) {
  379.  
  380.    int resname;
  381.    BYTE ch;
  382.  
  383.    writeline( "", outfile);
  384.  
  385.    ch = get_byte(infile);
  386.    if(ch == 0xFF) {
  387.        fread(&resname, sizeof(int), 1, infile);
  388.        if (resname == (int) VS_VERSION_INFO)
  389.           writestring("VS_VERSION_INFO ", outfile);
  390.        else
  391.           write_number(resname, outfile);
  392.    }
  393.    else {
  394.       write_char(ch, outfile);
  395.       ch = get_byte(infile);
  396.       while((!feof(infile)) && (ch != 0x00)) {
  397.          write_char(ch, outfile);
  398.          ch = get_byte(infile);
  399.       }
  400.    }
  401.  
  402. } /* write_version_number - end */
  403.  
  404.  
  405. /***************************************************
  406.    Get the memory flags for the current resource.
  407. ****************************************************/
  408. void get_mem_flags(FILE *infile) {
  409.  
  410.    /* Save the flag in a global variable.  See the header file! */
  411.    prev_mem_flag = get_word( infile );
  412.    return;
  413.  
  414. } /* get_mem_flags - end */
  415.  
  416.  
  417. /***************************************************
  418.    Write the memory flag values for the "special"
  419.    resources - cursors and icons. They're different
  420.    than the rest in that 0x20 means "discardable",
  421.    not "pure".
  422. ****************************************************/
  423. void write_special_mem_flag_values( WORD memtype, FILE *outfile) {
  424.  
  425.    if(memtype & 0x40)
  426.       writestring(" PRELOAD", outfile);
  427.    else
  428.       writestring(" LOADONCALL", outfile);
  429.  
  430.    if(memtype & 0x10)
  431.       writestring(" MOVEABLE", outfile);
  432.    else
  433.       writestring(" FIXED", outfile);
  434.  
  435.    if(memtype & 0x20)
  436.       writestring(" DISCARDABLE", outfile);
  437.  
  438. } /* write_special_mem_flag_values - end */
  439.  
  440.  
  441. /***************************************************
  442.    Write the memory flag values for the current resource.
  443. ****************************************************/
  444. void write_mem_flag_values( WORD memtype, FILE *outfile) {
  445.  
  446.    if(memtype & 0x40)
  447.       writestring(" PRELOAD", outfile);
  448.    else
  449.       writestring(" LOADONCALL", outfile);
  450.  
  451.    if(memtype & 0x10)
  452.       writestring(" MOVEABLE", outfile);
  453.    else
  454.       writestring(" FIXED", outfile);
  455.  
  456. /* This one isn't really used - "PURE" doesn't seem to make a difference.
  457.  
  458.    if(memtype & 0x20)
  459.       writestring(" PURE", outfile);
  460. */
  461.  
  462.    if(memtype & 0x1000)
  463.       writestring(" DISCARDABLE", outfile);
  464.  
  465. } /* write_mem_flag_values - end */
  466.  
  467.  
  468. /***************************************************
  469.    Get the memory flags for the current resource.
  470. ****************************************************/
  471. void write_mem_flags(FILE *infile, FILE *outfile) {
  472.  
  473.    WORD memtype;
  474.  
  475.    memtype = get_word( infile );
  476.    write_mem_flag_values( memtype, outfile );
  477.  
  478. } /* write_mem_flags - end */
  479.  
  480.  
  481. /***************************************************
  482.   Process the cursor resource
  483. ****************************************************/
  484. void process_cursor( FILE *infile ) {
  485.  
  486.    DWORD reslen;
  487.  
  488.    /* Skip it for now.  We'll come back and get the information   */
  489.    /* when we hit the group cursor resource - that has the header */
  490.    /* that has to go at the start of the .cur file.               */
  491.  
  492.    get_resource_name(infile);
  493.    get_mem_flags(infile);
  494.    reslen = get_resource_length(infile);
  495.  
  496.    fseek(infile, reslen, 1);
  497.  
  498. } /* process_cursor - end */
  499.  
  500.  
  501. /***************************************************
  502.   Process the bitmap resource
  503. ****************************************************/
  504. void process_bitmap(int restype, FILE *infile, FILE *outfile) {
  505.  
  506.    DWORD reslen;
  507.    BITMAPFILEHEADER bmfh;
  508.    char  datafilename[13];
  509.    FILE  *datafile;
  510.  
  511.    write_resource_name(infile, outfile);
  512.    write_char(' ', outfile);
  513.    writestring(res_array[restype], outfile);
  514.    write_mem_flags(infile, outfile);
  515.    write_char(' ', outfile);
  516.  
  517.    reslen = get_resource_length(infile);
  518.  
  519.    strcpy(datafilename, get_data_filename("BM", "BMP"));
  520.    if(strlen(datafilename) == 0) {
  521.       writeline("<Unable to open output file>", outfile);
  522.       fseek( infile, reslen, 1);
  523.       return;
  524.    }
  525.  
  526.    writeline( datafilename, outfile );
  527.  
  528.    if((datafile = fopen(datafilename, "wb")) == NULL) {
  529.       printf("Unable to open file %s\n", datafilename);
  530.       fseek( infile, reslen, 1);
  531.       return;
  532.    }
  533.  
  534.    bmfh.bfType      = 0x4D42;
  535.    bmfh.bfSize      = reslen + sizeof(BITMAPFILEHEADER);
  536.    bmfh.bfReserved1 = 0;
  537.    bmfh.bfReserved2 = 0;
  538.    bmfh.bfOffBits   = 0x76L;
  539.  
  540.    fwrite(&bmfh, sizeof(BITMAPFILEHEADER), 1, datafile);
  541.  
  542.    write_data( infile, datafile, reslen );
  543.    fclose( datafile );
  544.  
  545. } /* process_bitmap - end */
  546.  
  547.  
  548. /***************************************************
  549.   Process the flags for a popup menu
  550. ****************************************************/
  551. void process_popup_flags(DWORD menuitem, FILE *outfile) {
  552.  
  553.    if(menuitem & MF_GRAYED)
  554.       writestring(", GRAYED", outfile);
  555.    if(menuitem & MF_DISABLED)
  556.       writestring(", INACTIVE", outfile);
  557.    if(menuitem & MF_CHECKED)
  558.       writestring(", CHECKED", outfile);
  559.    if(menuitem & MF_MENUBARBREAK)
  560.       writestring(", MENUBARBREAK", outfile);
  561.    if(menuitem & MF_MENUBREAK)
  562.       writestring(", MENUBREAK", outfile);
  563.    if(menuitem & MF_END) {
  564.    }
  565.  
  566. } /* process_popup_flags - end */
  567.  
  568.  
  569. /***************************************************
  570.   Process the flags for a normal menuitem
  571. ****************************************************/
  572. void process_menuitem_flags(DWORD menuitem, FILE *outfile) {
  573.  
  574.    if(menuitem & MF_GRAYED)
  575.       writestring(", GRAYED", outfile);
  576.    if(menuitem & MF_DISABLED)
  577.       writestring(", INACTIVE", outfile);
  578.    if(menuitem & MF_CHECKED)
  579.       writestring(", CHECKED", outfile);
  580.    if(menuitem & MF_MENUBARBREAK)
  581.       writestring(", MENUBARBREAK", outfile);
  582.    if(menuitem & MF_MENUBREAK)
  583.       writestring(", MENUBREAK", outfile);
  584.    if(menuitem & MF_HELP)
  585.       writestring(", HELP", outfile);
  586.    if(menuitem & MF_END) {
  587.       writeline("", outfile);
  588.       decrease_indent();
  589.       write_indent(outfile);
  590.       writestring("}", outfile);
  591.    }
  592.  
  593. } /* process_menuitem_flags - end */
  594.  
  595.  
  596. /***************************************************
  597.   Process a normal menu resource
  598. ****************************************************/
  599. DWORD process_normal_menu(DWORD menuitem, FILE *infile, FILE *outfile) {
  600.  
  601.    WORD  menuid;
  602.    DWORD bytesread;
  603.  
  604.    fread(&menuid, sizeof(menuid), 1, infile);
  605.    bytesread = sizeof(menuid);
  606.  
  607.    increase_indent();
  608.    write_indent(outfile);
  609.  
  610.    writestring("MENUITEM ", outfile);
  611.    bytesread += write_item_text( infile, outfile);
  612.    if((bytesread - 1) > sizeof(menuid)) {
  613.       writestring(", ", outfile);
  614.       write_word( menuid, outfile);
  615.       process_menuitem_flags(menuitem, outfile);
  616.    }
  617.    else if((!menuid) && (!menuitem)) {
  618.       /* *** remove the leading quote from above */
  619.       writestring("SEPARATOR", outfile);
  620.    }
  621.    writeline("", outfile);
  622.  
  623.    decrease_indent();
  624.  
  625.    return(bytesread);
  626.  
  627. } /* process_normal_menu - end */
  628.  
  629.  
  630. /***************************************************
  631.   Process a popup menu resource
  632. ****************************************************/
  633. DWORD process_popup_menu(DWORD menuitem, FILE *infile, FILE *outfile) {
  634.  
  635.    DWORD bytesread;
  636.  
  637.    increase_indent();
  638.    write_indent(outfile);
  639.  
  640.    writestring("POPUP ", outfile);
  641.    bytesread = write_item_text( infile, outfile);
  642.    process_popup_flags(menuitem, outfile);
  643.    writeline(" {", outfile);
  644.  
  645.    return(bytesread);
  646.  
  647. } /* process_popup_menu - end */
  648.  
  649.  
  650. /***************************************************
  651.   Process the menu resource
  652. ****************************************************/
  653. void process_menu(int restype, FILE *infile, FILE *outfile) {
  654.  
  655.    DWORD reslen;
  656.    DWORD bytesread;
  657.    WORD  menuitem;
  658.    WORD  popupmenuitem;
  659.    struct MenuHeader menuhdr;
  660.  
  661.    write_resource_name(infile, outfile);
  662.    write_char(' ', outfile);
  663.    writestring(res_array[restype], outfile);
  664.    write_mem_flags(infile, outfile);
  665.    writeline(" {", outfile);
  666.    reslen = get_resource_length(infile);
  667.  
  668.    fread(&menuhdr, sizeof(struct MenuHeader), 1, infile);
  669.    reslen -= sizeof(struct MenuHeader);
  670.  
  671.    fread(&menuitem, sizeof(menuitem), 1, infile);
  672.    reslen -= sizeof(menuitem);
  673.    while(reslen) {
  674.  
  675.       if(menuitem & MF_POPUP) {
  676.           popupmenuitem = menuitem;
  677.           bytesread = process_popup_menu(  menuitem, infile, outfile);
  678.       }
  679.       else
  680.           bytesread = process_normal_menu( menuitem, infile, outfile);
  681.  
  682.       reslen -= bytesread;
  683.  
  684.       if(reslen) {
  685.          fread(&menuitem, sizeof(menuitem), 1, infile);
  686.          reslen -= sizeof(menuitem);
  687.       }
  688.       else if(popupmenuitem & MF_END) /* check last popup was the end */
  689.           writeline("}", outfile);
  690.  
  691.    }
  692.  
  693. } /* process_menu - end */
  694.  
  695.  
  696. /***************************************************
  697.   Process the icon resource
  698. ****************************************************/
  699. void process_icon( FILE *infile ) {
  700.  
  701.    DWORD reslen;
  702.  
  703.    /* Skip it for now.  We'll come back and get the information */
  704.    /* when we hit the group icon resource - that has the header */
  705.    /* that has to go at the start of the .ico file.             */
  706.  
  707.    get_resource_name(infile);
  708.    get_mem_flags(infile);
  709.    reslen = get_resource_length(infile);
  710.  
  711.    fseek(infile, reslen, 1);
  712.  
  713. } /* process_icon - end */
  714.  
  715.  
  716. /***************************************************
  717.   Write the dialog box size and shape information
  718. ****************************************************/
  719. void write_dialog_sizes( DIALOGHEADER dlg_hdr, FILE *outfile) {
  720.  
  721.    write_char(' ', outfile);
  722.    write_word( dlg_hdr.x, outfile );
  723.    writestring(", ", outfile);
  724.    write_word( dlg_hdr.y, outfile );
  725.    writestring(", ", outfile);
  726.    write_word( dlg_hdr.width, outfile );
  727.    writestring(", ", outfile);
  728.    write_word( dlg_hdr.height, outfile );
  729.    writeline("", outfile);
  730.  
  731. } /* write_dialog_sizes - end */
  732.  
  733.  
  734. /***************************************************
  735.   Check if the style is true; if so, write it out
  736. ****************************************************/
  737. void check_for_style( DWORD style, char *name, FILE *outfile ) {
  738.  
  739.    static WORD first_style = 1;
  740.    static WORD line_size = 6;          /* length of 'STYLE ' */
  741.  
  742.    if (style) {
  743.  
  744.       if (first_style) {
  745.          writestring("STYLE ", outfile);
  746.          first_style = 0;
  747.       }
  748.       else {
  749.          writestring(" | ", outfile);
  750.          line_size += 3;               /* add lenght of ' | ' */
  751.       }
  752.  
  753.       /* this is an attempt to keep the line length reasonable */
  754.       if ((line_size + strlen(name)) > 75) {
  755.          writeline("", outfile);
  756.          line_size = 6;
  757.          writestring("      ", outfile);
  758.       }
  759.  
  760.       writestring( name, outfile );
  761.       line_size += strlen(name);
  762.  
  763.    } /* if (style) - end */
  764.  
  765. } /* check_for_style - end */
  766.  
  767.  
  768. /***************************************************
  769.   Write the dialog box style information
  770. ****************************************************/
  771. void write_dialog_style( DIALOGHEADER dlg_hdr, FILE *outfile) {
  772.  
  773.    DWORD style;
  774.  
  775.    style = dlg_hdr.lStyle;
  776.  
  777.    check_for_style( style & WS_OVERLAPPED,   "WS_OVERLAPPED",   outfile );
  778.    check_for_style( style & WS_POPUP,        "WS_POPUP",        outfile );
  779.    check_for_style( style & WS_CHILD,        "WS_CHILD",        outfile );
  780.    check_for_style( style & WS_CLIPSIBLINGS, "WS_CLIPSIBLINGS", outfile );
  781.    check_for_style( style & WS_CLIPCHILDREN, "WS_CLIPCHILDREN", outfile );
  782.    check_for_style( style & WS_VISIBLE,      "WS_VISIBLE",      outfile );
  783.    check_for_style( style & WS_DISABLED,     "WS_DISABLED",     outfile );
  784.    check_for_style( style & WS_MINIMIZE,     "WS_MINIMIZE",     outfile );
  785.    check_for_style( style & WS_MAXIMIZE,     "WS_MAXIMIZE",     outfile );
  786.  
  787.    check_for_style( style & WS_BORDER,      "WS_BORDER",      outfile );
  788.    check_for_style( style & WS_DLGFRAME,    "WS_DLGFRAME",    outfile );
  789.    check_for_style( style & WS_VSCROLL,     "WS_VSCROLL",     outfile );
  790.    check_for_style( style & WS_HSCROLL,     "WS_HSCROLL",     outfile );
  791.    check_for_style( style & WS_SYSMENU,     "WS_SYSMENU",     outfile );
  792.    check_for_style( style & WS_THICKFRAME,  "WS_THICKFRAME",  outfile );
  793.    check_for_style( style & WS_MINIMIZEBOX, "WS_MINIMIZEBOX", outfile );
  794.    check_for_style( style & WS_MAXIMIZEBOX, "WS_MAXIMIZEBOX", outfile );
  795.  
  796.    check_for_style( style & WS_GROUP,          "WS_GROUP",          outfile );
  797.    check_for_style( style & WS_TABSTOP,        "WS_TABSTOP",        outfile );
  798.    check_for_style( style & WS_EX_TOPMOST,     "WS_EX_TOPMOST",     outfile );
  799.    check_for_style( style & WS_EX_ACCEPTFILES, "WS_EX_ACCEPTFILES", outfile );
  800.  
  801.    check_for_style( style & WS_EX_NOPARENTNOTIFY, "WS_EX_NOPARENTNOTIFY",
  802.                     outfile );
  803.  
  804.    check_for_style( style & DS_ABSALIGN,   "DS_ABSALIGN",   outfile );
  805.    check_for_style( style & DS_SYSMODAL,   "DS_SYSMODAL",   outfile );
  806.    check_for_style( style & DS_LOCALEDIT,  "DS_LOCALEDIT",  outfile );
  807.    check_for_style( style & DS_SETFONT,    "DS_SETFONT",    outfile );
  808.    check_for_style( style & DS_MODALFRAME, "DS_MODALFRAME", outfile );
  809.    check_for_style( style & DS_NOIDLEMSG,  "DS_NOIDLEMSG",  outfile );
  810.  
  811.    writeline("", outfile);
  812.  
  813. } /* write_dialog_style - end */
  814.  
  815.  
  816. /***************************************************
  817.   Write the dialog box menu name
  818. ****************************************************/
  819. void write_dialog_menu( FILE *infile, FILE *outfile) {
  820.  
  821.    BYTE ch;
  822.    WORD menuid;
  823.  
  824.    /* Read the first character and check for non-zero start byte */
  825.    ch = get_byte(infile);
  826.  
  827.    /* if first byte is 0x00, no menu name */
  828.    if(ch != 0x00) {
  829.  
  830.       writestring("MENU ", outfile);
  831.       if(ch == 0xFF) {
  832.          /* menu id is a number */
  833.          menuid = get_word( infile );
  834.          write_word(menuid, outfile);
  835.       }
  836.       else
  837.          get_custom_type( ch, infile, outfile);
  838.  
  839.       writeline("", outfile);
  840.    }
  841.  
  842. } /* write_dialog_menu - end */
  843.  
  844.  
  845. /***************************************************
  846.   Write the dialog box class name
  847. ****************************************************/
  848. void write_dialog_class( FILE *infile, FILE *outfile) {
  849.  
  850.    BYTE ch;
  851.  
  852.    /* Read the first character and check for non-zero start byte */
  853.    ch = get_byte(infile);
  854.  
  855.    /* get the resource type */
  856.    if(ch != 0x00) {
  857.       writestring("CLASS \"", outfile);
  858.       get_custom_type( ch, infile, outfile);
  859.       writeline("\"", outfile);
  860.    }
  861.  
  862. } /* write_dialog_class - end */
  863.  
  864.  
  865. /***************************************************
  866.   Write the dialog box font information
  867. ****************************************************/
  868. void write_dialog_font( FILE *infile, FILE *outfile) {
  869.  
  870.    WORD pointsize;
  871.  
  872.    writestring("FONT ", outfile);
  873.  
  874.    /* read and write the font point size */
  875.    pointsize = get_word( infile );
  876.    write_word( pointsize, outfile);
  877.    writestring(", ", outfile);
  878.  
  879.    /* write the font name */
  880.    (void) write_item_text( infile, outfile);
  881.  
  882.    writeline("", outfile);
  883.  
  884. } /* write_dialog_font - end */
  885.  
  886.  
  887. /***************************************************
  888.   Write the dialog box caption
  889. ****************************************************/
  890. void write_dialog_caption( FILE *infile, FILE *outfile) {
  891.  
  892.    BYTE ch;
  893.  
  894.    /* Read the first character and check for non-zero start byte */
  895.    ch = get_byte(infile);
  896.  
  897.    /* get the resource type */
  898.    if(ch != 0x00) {
  899.       writestring("CAPTION \"", outfile);
  900.       get_custom_type( ch, infile, outfile);
  901.       writeline("\"", outfile);
  902.    }
  903.  
  904. } /* write_dialog_caption - end */
  905.  
  906.  
  907. /***************************************************
  908.   Write the start of the "CONTROL" string 
  909. ****************************************************/
  910. void write_control_header( char *text, WORD id, FILE *outfile) {
  911.  
  912.    write_indent(outfile);
  913.  
  914.    writestring("CONTROL \"", outfile);
  915.    writestring( text, outfile);
  916.    writestring( "\", ", outfile);
  917.  
  918.    /* check if id is -1 */
  919.    if (id != 0xFFFF)
  920.       write_word( id, outfile);
  921.    else
  922.       writestring( "-1", outfile);
  923.  
  924.    writestring( ", ", outfile);
  925.  
  926. } /* write_control_header - end */
  927.  
  928.  
  929. /***************************************************
  930.   Write the end of the "CONTROL" statement.
  931. ****************************************************/
  932. void write_control_end( CONTROLDATA ctrl, FILE *outfile) {
  933.  
  934.    char string[50];
  935.  
  936.    /* write the size/dimensions of the object */
  937.    write_indent(outfile);
  938.    sprintf( string, "%hu, %hu, %hu, %hu", ctrl.x, ctrl.y, 
  939.             ctrl.width, ctrl.height);
  940.    writeline( string, outfile);
  941.  
  942. } /* write_control_end - end */
  943.  
  944.  
  945. /***************************************************
  946.   Write the style for the dialog box
  947. ****************************************************/
  948. void check_for_dlg_style( DWORD style, WORD *first_style, WORD *line_len,
  949.                        char *style_name, FILE *outfile ) {
  950.  
  951.    if (style) {
  952.  
  953.       /* if first_style = 2, write out a leading comma */
  954.       if (*first_style == 2) {
  955.          writestring(", ", outfile);
  956.          *first_style = 1;
  957.       }
  958.  
  959.       if (*first_style == 1) {
  960.  
  961.          /* this is the first style, so just write out the style name */
  962.          writestring( style_name, outfile);
  963.          *first_style = 0;
  964.          *line_len += strlen(style_name);
  965.  
  966.       }
  967.       else {
  968.  
  969.          /* this is after first style, so write '|' for concat */
  970.          writestring(" | ", outfile);
  971.          *line_len += (3 + strlen(style_name));
  972.  
  973.          /* try to keep each line to a reasonable length */
  974.          if (*line_len >= 75) {
  975.             writeline("", outfile);
  976.             write_indent(outfile);
  977.             *line_len = strlen(style_name);
  978.          }
  979.  
  980.          /* write out the name of the style */
  981.          writestring(style_name, outfile);
  982.  
  983.       } /* if (*first_style) / else - end */
  984.  
  985.    } /* if (style) - end */
  986.  
  987. } /* check_for_dlg_style - end */
  988.  
  989.  
  990. /***************************************************
  991.   Process the button control in the dialog box
  992. ****************************************************/
  993. void process_control_button( DWORD style, FILE *outfile ) {
  994.  
  995.    WORD first_style = 1;
  996.    WORD line_len = 0;
  997.  
  998.    writestring( "\"button\", ", outfile);
  999.  
  1000.    check_for_dlg_style( BS_LEFTTEXT & style, &first_style, &line_len,
  1001.                           "BS_LEFTTEXT", outfile );
  1002.    check_for_dlg_style( WS_TABSTOP & style, &first_style, &line_len,
  1003.                           "WS_TABSTOP", outfile );
  1004.    check_for_dlg_style( WS_GROUP & style, &first_style, &line_len,
  1005.                           "WS_GROUP", outfile );
  1006.    check_for_dlg_style( WS_DISABLED & style, &first_style, &line_len,
  1007.                           "WS_DISABLED", outfile );
  1008.  
  1009.    if(first_style == 0)
  1010.       writestring(" | ", outfile);
  1011.  
  1012.    /* checked for non-exclusive properties, now clear out high bits */
  1013.    style &= 0xF;
  1014.  
  1015.    if (style == BS_DEFPUSHBUTTON)
  1016.       writestring("BS_DEFPUSHBUTTON", outfile);
  1017.    else if (style == BS_CHECKBOX)
  1018.       writestring("BS_CHECKBOX", outfile);
  1019.    else if (style == BS_AUTOCHECKBOX)
  1020.       writestring("BS_AUTOCHECKBOX", outfile);
  1021.    else if (style == BS_RADIOBUTTON)
  1022.       writestring("BS_RADIOBUTTON", outfile);
  1023.    else if (style == BS_3STATE)
  1024.       writestring("BS_3STATE", outfile);
  1025.    else if (style == BS_AUTO3STATE)
  1026.       writestring("BS_AUTO3STATE", outfile);
  1027.    else if (style == BS_GROUPBOX)
  1028.       writestring("BS_GROUPBOX", outfile);
  1029.    else if (style == BS_USERBUTTON)
  1030.       writestring("BS_USERBUTTON", outfile);
  1031.    else if (style == BS_AUTORADIOBUTTON)
  1032.       writestring("BS_AUTORADIOBUTTON", outfile);
  1033.    else if (style == BS_OWNERDRAW)
  1034.       writestring("BS_OWNERDRAW", outfile);
  1035.    else
  1036.       writestring("BS_PUSHBUTTON", outfile);
  1037.  
  1038.    writeline(",", outfile);
  1039.  
  1040. } /* process_control_button - end */
  1041.  
  1042.  
  1043. /***************************************************
  1044.   Process the edit control in the dialog box
  1045. ****************************************************/
  1046. void process_control_edit( CONTROLDATA ctrl, FILE *outfile ) {
  1047.  
  1048.    WORD first_style = 2;
  1049.    char string[100];
  1050.    WORD line_len = 0;
  1051.    DWORD style;
  1052.  
  1053.    style = ctrl.lStyle;
  1054.  
  1055.    write_indent(outfile);
  1056.    sprintf( string, "EDITTEXT %hu, %hu, %hu, %hu, %hu", ctrl.id, ctrl.x, 
  1057.             ctrl.y, ctrl.width, ctrl.height);
  1058.    line_len = strlen(string);
  1059.    writestring( string, outfile);
  1060.  
  1061.    check_for_dlg_style( ES_LEFT & style, &first_style, &line_len,
  1062.                           "ES_LEFT", outfile );
  1063.    check_for_dlg_style( ES_CENTER & style, &first_style, &line_len,
  1064.                           "ES_CENTER", outfile );
  1065.    check_for_dlg_style( ES_RIGHT & style, &first_style, &line_len,
  1066.                           "ES_RIGHT", outfile );
  1067.    check_for_dlg_style( ES_MULTILINE & style, &first_style, &line_len,
  1068.                           "ES_MULTILINE", outfile );
  1069.    check_for_dlg_style( ES_UPPERCASE & style, &first_style, &line_len,
  1070.                           "ES_UPPERCASE", outfile );
  1071.    check_for_dlg_style( ES_LOWERCASE & style, &first_style, &line_len,
  1072.                           "ES_LOWERCASE", outfile );
  1073.    check_for_dlg_style( ES_PASSWORD & style, &first_style, &line_len,
  1074.                           "ES_PASSWORD", outfile );
  1075.    check_for_dlg_style( ES_AUTOVSCROLL & style, &first_style, &line_len,
  1076.                           "ES_AUTOVSCROLL", outfile );
  1077.    check_for_dlg_style( ES_AUTOHSCROLL & style, &first_style, &line_len,
  1078.                           "ES_AUTOHSCROLL", outfile );
  1079.    check_for_dlg_style( ES_NOHIDESEL & style, &first_style, &line_len,
  1080.                           "ES_NOHIDESEL", outfile );
  1081.    check_for_dlg_style( ES_OEMCONVERT & style, &first_style, &line_len,
  1082.                           "ES_OEMCONVERT", outfile );
  1083.    check_for_dlg_style( ES_READONLY & style, &first_style, &line_len,
  1084.                           "ES_READONLY", outfile );
  1085.    check_for_dlg_style( ES_WANTRETURN & style, &first_style, &line_len,
  1086.                           "ES_WANTRETURN", outfile );
  1087.  
  1088.    check_for_dlg_style( WS_TABSTOP & style, &first_style, &line_len,
  1089.                           "WS_TABSTOP", outfile );
  1090.    check_for_dlg_style( WS_GROUP & style, &first_style, &line_len,
  1091.                           "WS_GROUP", outfile );
  1092.    check_for_dlg_style( WS_VSCROLL & style, &first_style, &line_len,
  1093.                           "WS_VSCROLL", outfile );
  1094.    check_for_dlg_style( WS_HSCROLL & style, &first_style, &line_len,
  1095.                           "WS_HSCROLL", outfile );
  1096.    check_for_dlg_style( WS_DISABLED & style, &first_style, &line_len,
  1097.                           "WS_DISABLED", outfile );
  1098.  
  1099.    writeline("", outfile);
  1100.  
  1101. } /* process_control_edit - end */
  1102.  
  1103.  
  1104. /***************************************************
  1105.   Process the static control in the dialog box
  1106. ****************************************************/
  1107. void process_control_static( DWORD style, FILE *outfile ) {
  1108.  
  1109.    WORD first_style = 1;
  1110.    WORD line_len = 0;
  1111.  
  1112.    writestring( "\"static\", ", outfile);
  1113.  
  1114.    check_for_dlg_style( SS_NOPREFIX & style, &first_style, &line_len,
  1115.                           "SS_NOPREFIX", outfile );
  1116.    check_for_dlg_style( WS_GROUP & style, &first_style, &line_len,
  1117.                           "WS_GROUP", outfile );
  1118.    check_for_dlg_style( WS_TABSTOP & style, &first_style, &line_len,
  1119.                           "WS_TABSTOP", outfile );
  1120.  
  1121.    if(first_style == 0)
  1122.       writestring(" | ", outfile);
  1123.  
  1124.    style &= 0xF;
  1125.  
  1126.    if ( style == SS_CENTER )
  1127.       writestring( "SS_CENTER", outfile);
  1128.    else if ( style == SS_RIGHT )
  1129.       writestring( "SS_RIGHT", outfile);
  1130.    else if ( style == SS_ICON )
  1131.       writestring( "SS_ICON", outfile);
  1132.    else if ( style == SS_BLACKRECT )
  1133.       writestring( "SS_BLACKRECT", outfile);
  1134.    else if ( style == SS_GRAYRECT )
  1135.       writestring( "SS_GRAYRECT", outfile);
  1136.    else if ( style == SS_WHITERECT )
  1137.       writestring( "SS_WHITERECT", outfile);
  1138.    else if ( style == SS_BLACKFRAME )
  1139.       writestring( "SS_BLACKFRAME", outfile);
  1140.    else if ( style == SS_GRAYFRAME )
  1141.       writestring( "SS_GRAYFRAME", outfile);
  1142.    else if ( style == SS_WHITEFRAME )
  1143.       writestring( "SS_WHITEFRAME", outfile);
  1144.    else if ( style == SS_SIMPLE )
  1145.       writestring( "SS_SIMPLE", outfile);
  1146.    else if ( style == SS_LEFTNOWORDWRAP )
  1147.       writestring( "SS_LEFTNOWORDWRAP", outfile);
  1148.    else
  1149.       writestring( "SS_LEFT", outfile);
  1150.  
  1151.    writeline(",", outfile);
  1152.  
  1153. } /* process_control_static - end */
  1154.  
  1155.  
  1156. /***************************************************
  1157.   Process the list box control in the dialog box
  1158. ****************************************************/
  1159. void process_control_listbox( CONTROLDATA ctrl, FILE *outfile ) {
  1160.  
  1161.    WORD first_style = 2;
  1162.    char string[100];
  1163.    WORD line_len = 0;
  1164.    DWORD style;
  1165.  
  1166.    style = ctrl.lStyle;
  1167.  
  1168.    write_indent(outfile);
  1169.    sprintf( string, "LISTBOX %hu, %hu, %hu, %hu, %hu", ctrl.id, ctrl.x, 
  1170.             ctrl.y, ctrl.width, ctrl.height);
  1171.    line_len = strlen(string);
  1172.    writestring( string, outfile);
  1173.  
  1174.    check_for_dlg_style( LBS_NOTIFY & style, &first_style, &line_len,
  1175.                           "LBS_NOTIFY", outfile );
  1176.    check_for_dlg_style( LBS_SORT & style, &first_style, &line_len,
  1177.                           "LBS_SORT", outfile );
  1178.    check_for_dlg_style( LBS_NOREDRAW & style, &first_style, &line_len,
  1179.                           "LBS_NOREDRAW", outfile );
  1180.    check_for_dlg_style( LBS_MULTIPLESEL & style, &first_style, &line_len,
  1181.                           "LBS_MULTIPLESEL", outfile );
  1182.    check_for_dlg_style( LBS_OWNERDRAWFIXED & style, &first_style, &line_len,
  1183.                           "LBS_OWNERDRAWFIXED", outfile );
  1184.    check_for_dlg_style( LBS_OWNERDRAWVARIABLE & style, &first_style, &line_len,
  1185.                           "LBS_OWNERDRAWVARIABLE", outfile );
  1186.    check_for_dlg_style( LBS_HASSTRINGS & style, &first_style, &line_len,
  1187.                           "LBS_HASSTRINGS", outfile );
  1188.    check_for_dlg_style( LBS_USETABSTOPS & style, &first_style, &line_len,
  1189.                           "LBS_USETABSTOPS", outfile );
  1190.    check_for_dlg_style( LBS_NOINTEGRALHEIGHT & style, &first_style, &line_len,
  1191.                           "LBS_NOINTEGRALHEIGHT", outfile );
  1192.    check_for_dlg_style( LBS_MULTICOLUMN & style, &first_style, &line_len,
  1193.                           "LBS_MULTICOLUMN", outfile );
  1194.    check_for_dlg_style( LBS_WANTKEYBOARDINPUT & style, &first_style, &line_len,
  1195.                           "LBS_WANTKEYBOARDINPUT", outfile );
  1196.    check_for_dlg_style( LBS_EXTENDEDSEL & style, &first_style, &line_len,
  1197.                           "LBS_EXTENDEDSEL", outfile );
  1198.    check_for_dlg_style( LBS_DISABLENOSCROLL & style, &first_style, &line_len,
  1199.                           "LBS_DISABLENOSCROLL", outfile );
  1200.  
  1201.    check_for_dlg_style( WS_BORDER & style, &first_style, &line_len,
  1202.                           "WS_BORDER", outfile );
  1203.    check_for_dlg_style( WS_VSCROLL & style, &first_style, &line_len,
  1204.                           "WS_VSCROLL", outfile );
  1205.  
  1206.    writeline("", outfile);
  1207.  
  1208. } /* process_control_listbox - end */
  1209.  
  1210.  
  1211. /***************************************************
  1212.   Process the scroll bar control in the dialog box
  1213. ****************************************************/
  1214. void process_control_scrollbar( CONTROLDATA ctrl, FILE *outfile ) {
  1215.  
  1216.    WORD first_style = 2;
  1217.    char string[100];
  1218.    WORD line_len = 0;
  1219.    DWORD style;
  1220.  
  1221.    style = ctrl.lStyle;
  1222.  
  1223.    write_indent(outfile);
  1224.    sprintf( string, "SCROLLBAR %hu, %hu, %hu, %hu, %hu", ctrl.id, ctrl.x, 
  1225.             ctrl.y, ctrl.width, ctrl.height);
  1226.    line_len = strlen(string);
  1227.    writestring( string, outfile);
  1228.  
  1229.    check_for_dlg_style( SBS_HORZ & style, &first_style, &line_len,
  1230.                           "SBS_HORZ", outfile );
  1231.    check_for_dlg_style( SBS_VERT & style, &first_style, &line_len,
  1232.                           "SBS_VERT", outfile );
  1233.    check_for_dlg_style( SBS_TOPALIGN & style, &first_style, &line_len,
  1234.                           "SBS_TOPALIGN", outfile );
  1235.    check_for_dlg_style( SBS_BOTTOMALIGN & style, &first_style, &line_len,
  1236.                           "SBS_BOTTOMALIGN", outfile );
  1237.    check_for_dlg_style( SBS_SIZEBOX & style, &first_style, &line_len,
  1238.                           "SBS_SIZEBOX", outfile );
  1239.  
  1240.    check_for_dlg_style( WS_TABSTOP & style, &first_style, &line_len,
  1241.                           "WS_TABSTOP", outfile );
  1242.    check_for_dlg_style( WS_GROUP & style, &first_style, &line_len,
  1243.                           "WS_GROUP", outfile );
  1244.    check_for_dlg_style( WS_DISABLED & style, &first_style, &line_len,
  1245.                           "WS_DISABLED", outfile );
  1246.  
  1247.    writeline("", outfile);
  1248.  
  1249. } /* process_control_scrollbar - end */
  1250.  
  1251.  
  1252. /***************************************************
  1253.   Process the combo box control in the dialog box
  1254. ****************************************************/
  1255. void process_control_combobox( CONTROLDATA ctrl, FILE *outfile) {
  1256.  
  1257.    WORD first_style = 2;
  1258.    WORD line_len = 0;
  1259.    char string[100];
  1260.    DWORD style;
  1261.  
  1262.    style = ctrl.lStyle;
  1263.  
  1264.    write_indent(outfile);
  1265.    sprintf( string, "COMBOBOX %hu, %hu, %hu, %hu, %hu", ctrl.id, ctrl.x, 
  1266.             ctrl.y, ctrl.width, ctrl.height);
  1267.    line_len = strlen(string);
  1268.    writestring( string, outfile);
  1269.  
  1270.    check_for_dlg_style( CBS_SIMPLE & style, &first_style, &line_len,
  1271.                           "CBS_SIMPLE", outfile );
  1272.    check_for_dlg_style( CBS_DROPDOWN & style, &first_style, &line_len,
  1273.                           "CBS_DROPDOWN", outfile );
  1274.    check_for_dlg_style( CBS_OWNERDRAWFIXED & style, &first_style, &line_len,
  1275.                           "CBS_OWNERDRAWFIXED", outfile );
  1276.    check_for_dlg_style( CBS_OWNERDRAWVARIABLE & style, &first_style, &line_len,
  1277.                           "CBS_OWNERDRAWVARIABLE", outfile );
  1278.    check_for_dlg_style( CBS_AUTOHSCROLL & style, &first_style, &line_len,
  1279.                           "CBS_AUTOHSCROLL", outfile );
  1280.    check_for_dlg_style( CBS_OEMCONVERT & style, &first_style, &line_len,
  1281.                           "CBS_OEMCONVERT", outfile );
  1282.    check_for_dlg_style( CBS_SORT & style, &first_style, &line_len,
  1283.                           "CBS_SORT", outfile );
  1284.    check_for_dlg_style( CBS_HASSTRINGS & style, &first_style, &line_len,
  1285.                           "CBS_HASSTRINGS", outfile );
  1286.    check_for_dlg_style( CBS_NOINTEGRALHEIGHT & style, &first_style, &line_len,
  1287.                           "CBS_NOINTEGRALHEIGHT", outfile );
  1288.    check_for_dlg_style( CBS_DISABLENOSCROLL & style, &first_style, &line_len,
  1289.                           "CBS_DISABLENOSCROLL", outfile );
  1290.  
  1291.    check_for_dlg_style( WS_TABSTOP & style, &first_style, &line_len,
  1292.                           "WS_TABSTOP", outfile );
  1293.    check_for_dlg_style( WS_GROUP & style, &first_style, &line_len,
  1294.                           "WS_GROUP", outfile );
  1295.    check_for_dlg_style( WS_VSCROLL & style, &first_style, &line_len,
  1296.                           "WS_VSCROLL", outfile );
  1297.    check_for_dlg_style( WS_DISABLED & style, &first_style, &line_len,
  1298.                           "WS_DISABLED", outfile );
  1299.  
  1300.    writeline("", outfile);
  1301.  
  1302. } /* process_control_combobox - end */
  1303.  
  1304.  
  1305. /***************************************************
  1306.   Process each control in the dialog box
  1307. ****************************************************/
  1308. void process_control( FILE *infile, FILE *outfile ) {
  1309.  
  1310.    CONTROLDATA ctrl;
  1311.    BYTE class_id;
  1312.    BYTE ch;
  1313.    char ctrl_text[260];
  1314.    char ctrl_class[260];
  1315.    WORD index = 0;
  1316.  
  1317.    fread( &ctrl, sizeof(CONTROLDATA), 1, infile);
  1318.  
  1319.    /* read the class type (if 0x8?) or the string (otherwise) */
  1320.    ch = get_byte(infile);
  1321.    if (ch & 0x80) {
  1322.       class_id = ch;
  1323.    }
  1324.    else {
  1325.       class_id = 0x00;
  1326.       while (ch != 0x00) {
  1327.          if (index < 260) {
  1328.             ctrl_class[index] = ch;
  1329.             ++index;
  1330.          }
  1331.          ch = get_byte(infile);
  1332.       }
  1333.    }
  1334.    ctrl_class[index] = '\0';
  1335.  
  1336.    /* read the text field */
  1337.    ch = get_byte(infile);
  1338.    index = 0;
  1339.    while (ch != 0x00) {
  1340.       if (index < 260) {
  1341.          ctrl_text[index] = ch;
  1342.          ++index;
  1343.       }
  1344.       ch = get_byte(infile);
  1345.    }
  1346.    ctrl_text[index] = '\0';
  1347.  
  1348.    /* read the extra 0x00 */
  1349.    ch = get_byte(infile);
  1350.    if (ch != 0x00) {
  1351.       writestring("Error ** ch =>", outfile);
  1352.       write_char( ch, outfile);
  1353.       writeline("< - should be 00", outfile);
  1354.    }
  1355.  
  1356.    increase_indent();
  1357.  
  1358.    if (class_id & 0x80) {
  1359.  
  1360.       switch (class_id) {
  1361.  
  1362.          /* Control is a button */
  1363.          case 0x80: 
  1364.             write_control_header( ctrl_text, ctrl.id, outfile);
  1365.             process_control_button( ctrl.lStyle, outfile );
  1366.             write_control_end( ctrl, outfile);
  1367.             break;
  1368.  
  1369.          /* Control is an edit widget */
  1370.          case 0x81: 
  1371.             process_control_edit( ctrl, outfile );
  1372.             break;
  1373.  
  1374.          /* Control is a static widget */
  1375.          case 0x82: 
  1376.             write_control_header( ctrl_text, ctrl.id, outfile);
  1377.             process_control_static( ctrl.lStyle, outfile );
  1378.             write_control_end( ctrl, outfile);
  1379.             break;
  1380.  
  1381.          /* Control is a listbox */
  1382.          case 0x83: 
  1383.             process_control_listbox( ctrl, outfile );
  1384.             break;
  1385.  
  1386.          /* Control is a scrollbar */
  1387.          case 0x84: 
  1388.             process_control_scrollbar( ctrl, outfile );
  1389.             break;
  1390.  
  1391.          /* Control is a combobox */
  1392.          case 0x85: 
  1393.             process_control_combobox( ctrl, outfile );
  1394.             break;
  1395.  
  1396.          default: 
  1397.             break;  /* Unknown type, so skip */
  1398.       }
  1399.  
  1400.    }
  1401.    else {
  1402.       ; /* The resource type is unknown, so skip */
  1403.    }
  1404.  
  1405.    decrease_indent();
  1406.  
  1407. } /* process_control - end */
  1408.  
  1409.  
  1410. /***************************************************
  1411.   Process the dialog resource
  1412. ****************************************************/
  1413. void process_dialog(int restype, FILE *infile, FILE *outfile) {
  1414.  
  1415.    DIALOGHEADER dlg_hdr;
  1416.  
  1417.    /* write the generic dialog box info */
  1418.    write_resource_name(infile, outfile);
  1419.    write_char(' ', outfile);
  1420.    writestring(res_array[restype], outfile);
  1421.    write_mem_flags(infile, outfile);
  1422.  
  1423.    /* get the dialog box resource length, and the dialog box header */
  1424.    (void) get_resource_length(infile);
  1425.    fread( &dlg_hdr, sizeof(DIALOGHEADER), 1, infile);
  1426.  
  1427.    write_dialog_sizes( dlg_hdr, outfile);
  1428.    write_dialog_style( dlg_hdr, outfile);
  1429.    write_dialog_menu(  infile,  outfile);
  1430.    write_dialog_class( infile,  outfile);
  1431.    write_dialog_caption( infile, outfile);
  1432.  
  1433.    if (dlg_hdr.lStyle & DS_SETFONT)
  1434.       write_dialog_font( infile, outfile);
  1435.  
  1436.    writeline("BEGIN", outfile);
  1437.  
  1438.    while(dlg_hdr.bNumberOfItems) {
  1439.  
  1440.       process_control( infile, outfile );
  1441.  
  1442.       dlg_hdr.bNumberOfItems -= 1;
  1443.    }
  1444.  
  1445.  
  1446.    writeline("END", outfile);
  1447.  
  1448. } /* process_dialog - end */
  1449.  
  1450.  
  1451. /***************************************************
  1452.   Process the string resource
  1453. ****************************************************/
  1454. void process_string(int restype, FILE *infile, FILE *outfile) {
  1455.  
  1456.    WORD  sID;
  1457.    int   index;
  1458.    BYTE  ch;
  1459.    BYTE  strlen;
  1460.  
  1461.    sID = get_resource_number(infile);
  1462.    if (StringCount == 0) {
  1463.       writeline( "", outfile);
  1464.       writestring(res_array[restype], outfile);
  1465.       write_mem_flags(infile, outfile);
  1466.       writeline(" {", outfile);
  1467.    }
  1468.    else {
  1469.       get_mem_flags(infile);
  1470.    }
  1471.  
  1472.    ++StringCount;
  1473.  
  1474.    increase_indent();
  1475.  
  1476.    (void) get_resource_length(infile);
  1477.  
  1478.    for(index = 0; index < 16; ++index) {
  1479.       if((strlen = get_byte(infile)) != 0x00) {
  1480.          write_indent(outfile);
  1481.          sID = index + ((sID - 1) * 16);
  1482.          write_word( sID, outfile);
  1483.          writestring(", \"", outfile);
  1484.          while(strlen--) {
  1485.             ch = get_byte(infile);
  1486.             write_char(ch, outfile);
  1487.          }
  1488.          writeline("\"", outfile);
  1489.       }
  1490.    }
  1491.  
  1492.    decrease_indent();
  1493.  
  1494.    if(StringCount >= 16) {
  1495.       writeline("}", outfile);
  1496.       StringCount = 0;
  1497.    }
  1498.  
  1499. } /* process_string - end */
  1500.  
  1501.  
  1502. /***************************************************
  1503.   Process the fontdir resource
  1504. ****************************************************/
  1505. void process_fontdir( FILE *infile ) {
  1506.  
  1507.    DWORD reslen;
  1508.  
  1509.    get_resource_name(infile);
  1510.    get_mem_flags(infile);
  1511.    reslen = get_resource_length(infile);
  1512.  
  1513.    fseek(infile, reslen, 1);
  1514.  
  1515. } /* process_fontdir - end */
  1516.  
  1517.  
  1518. /***************************************************
  1519.   Process the font resource
  1520. ****************************************************/
  1521. void process_font(int restype, FILE *infile, FILE *outfile) {
  1522.  
  1523.    DWORD reslen;
  1524.    char  datafilename[13];
  1525.    FILE  *datafile;
  1526.  
  1527.    write_resource_name(infile, outfile);
  1528.    write_char(' ', outfile);
  1529.    writestring(res_array[restype], outfile);
  1530.    write_mem_flags(infile, outfile);
  1531.    write_char(' ', outfile);
  1532.  
  1533.    reslen = get_resource_length(infile);
  1534.  
  1535.    strcpy(datafilename, get_data_filename("FO", "FON"));
  1536.    if(strlen(datafilename) == 0) {
  1537.       writeline("<Unable to open output file>", outfile);
  1538.       fseek( infile, reslen, 1);
  1539.       return;
  1540.    }
  1541.  
  1542.    writeline( datafilename, outfile );
  1543.  
  1544.    if((datafile = fopen(datafilename, "wb")) == NULL) {
  1545.       printf("Unable to open file %s\n", datafilename);
  1546.       fseek( infile, reslen, 1);
  1547.       return;
  1548.    }
  1549.  
  1550.    write_data( infile, datafile, reslen );
  1551.    fclose( datafile );
  1552.  
  1553. } /* process_font - end */
  1554.  
  1555.  
  1556. /***************************************************
  1557.   Write the virtual character for the current accelerator
  1558. ****************************************************/
  1559. void write_virtual_accel_event( WORD wEvent, FILE *outfile) {
  1560.  
  1561.    switch(wEvent) {
  1562.  
  1563.       case VK_LBUTTON:
  1564.          writestring( "VK_LBUTTON", outfile);
  1565.          break;
  1566.  
  1567.       case VK_RBUTTON:
  1568.          writestring( "VK_RBUTTON", outfile);
  1569.          break;
  1570.  
  1571.       case VK_CANCEL:
  1572.          writestring( "VK_CANCEL", outfile);
  1573.          break;
  1574.  
  1575.       case VK_MBUTTON:
  1576.          writestring( "VK_MBUTTON", outfile);
  1577.          break;
  1578.  
  1579.       case VK_BACK:
  1580.          writestring( "VK_BACK", outfile);
  1581.          break;
  1582.  
  1583.       case VK_TAB:
  1584.          writestring( "VK_TAB", outfile);
  1585.          break;
  1586.  
  1587.       case VK_CLEAR:
  1588.          writestring( "VK_CLEAR", outfile);
  1589.          break;
  1590.  
  1591.       case VK_RETURN:
  1592.          writestring( "VK_RETURN", outfile);
  1593.          break;
  1594.  
  1595.       case VK_SHIFT:
  1596.          writestring( "VK_SHIFT", outfile);
  1597.          break;
  1598.  
  1599.       case VK_CONTROL:
  1600.          writestring( "VK_CONTROL", outfile);
  1601.          break;
  1602.  
  1603.       case VK_MENU:
  1604.          writestring( "VK_MENU", outfile);
  1605.          break;
  1606.  
  1607.       case VK_PAUSE:
  1608.          writestring( "VK_PAUSE", outfile);
  1609.          break;
  1610.  
  1611.       case VK_CAPITAL:
  1612.          writestring( "VK_CAPITAL", outfile);
  1613.          break;
  1614.  
  1615.       case VK_ESCAPE:
  1616.          writestring( "VK_ESCAPE", outfile);
  1617.          break;
  1618.  
  1619.       case VK_SPACE:
  1620.          writestring( "VK_SPACE", outfile);
  1621.          break;
  1622.  
  1623.       case VK_PRIOR:
  1624.          writestring( "VK_PRIOR", outfile);
  1625.          break;
  1626.  
  1627.       case VK_NEXT:
  1628.          writestring( "VK_NEXT", outfile);
  1629.          break;
  1630.  
  1631.       case VK_END:
  1632.          writestring( "VK_END", outfile);
  1633.          break;
  1634.  
  1635.       case VK_HOME:
  1636.          writestring( "VK_HOME", outfile);
  1637.          break;
  1638.  
  1639.       case VK_LEFT:
  1640.          writestring( "VK_LEFT", outfile);
  1641.          break;
  1642.  
  1643.       case VK_UP:
  1644.          writestring( "VK_UP", outfile);
  1645.          break;
  1646.  
  1647.       case VK_RIGHT:
  1648.          writestring( "VK_RIGHT", outfile);
  1649.          break;
  1650.  
  1651.       case VK_DOWN:
  1652.          writestring( "VK_DOWN", outfile);
  1653.          break;
  1654.  
  1655.       case VK_SELECT:
  1656.          writestring( "VK_SELECT", outfile);
  1657.          break;
  1658.  
  1659.       case VK_PRINT:
  1660.          writestring( "VK_PRINT", outfile);
  1661.          break;
  1662.  
  1663.       case VK_EXECUTE:
  1664.          writestring( "VK_EXECUTE", outfile);
  1665.          break;
  1666.  
  1667.       case VK_SNAPSHOT:
  1668.          writestring( "VK_SNAPSHOT", outfile);
  1669.          break;
  1670.  
  1671.       case VK_INSERT:
  1672.          writestring( "VK_INSERT", outfile);
  1673.          break;
  1674.  
  1675.       case VK_DELETE:
  1676.          writestring( "VK_DELETE", outfile);
  1677.          break;
  1678.  
  1679.       case VK_HELP:
  1680.          writestring( "VK_HELP", outfile);
  1681.          break;
  1682.  
  1683.       case VK_NUMPAD0:
  1684.          writestring( "VK_NUMPAD0", outfile);
  1685.          break;
  1686.  
  1687.       case VK_NUMPAD1:
  1688.          writestring( "VK_NUMPAD1", outfile);
  1689.          break;
  1690.  
  1691.       case VK_NUMPAD2:
  1692.          writestring( "VK_NUMPAD2", outfile);
  1693.          break;
  1694.  
  1695.       case VK_NUMPAD3:
  1696.          writestring( "VK_NUMPAD3", outfile);
  1697.          break;
  1698.  
  1699.       case VK_NUMPAD4:
  1700.          writestring( "VK_NUMPAD4", outfile);
  1701.          break;
  1702.  
  1703.       case VK_NUMPAD5:
  1704.          writestring( "VK_NUMPAD5", outfile);
  1705.          break;
  1706.  
  1707.       case VK_NUMPAD6:
  1708.          writestring( "VK_NUMPAD6", outfile);
  1709.          break;
  1710.  
  1711.       case VK_NUMPAD7:
  1712.          writestring( "VK_NUMPAD7", outfile);
  1713.          break;
  1714.  
  1715.       case VK_NUMPAD8:
  1716.          writestring( "VK_NUMPAD8", outfile);
  1717.          break;
  1718.  
  1719.       case VK_NUMPAD9:
  1720.          writestring( "VK_NUMPAD9", outfile);
  1721.          break;
  1722.  
  1723.       case VK_MULTIPLY:
  1724.          writestring( "VK_MULTIPLY", outfile);
  1725.          break;
  1726.  
  1727.       case VK_ADD:
  1728.          writestring( "VK_ADD", outfile);
  1729.          break;
  1730.  
  1731.       case VK_SEPARATOR:
  1732.          writestring( "VK_SEPARATOR", outfile);
  1733.          break;
  1734.  
  1735.       case VK_SUBTRACT:
  1736.          writestring( "VK_SUBTRACT", outfile);
  1737.          break;
  1738.  
  1739.       case VK_DECIMAL:
  1740.          writestring( "VK_DECIMAL", outfile);
  1741.          break;
  1742.  
  1743.       case VK_DIVIDE:
  1744.          writestring( "VK_DIVIDE", outfile);
  1745.          break;
  1746.  
  1747.       case VK_F1:
  1748.          writestring( "VK_F1", outfile);
  1749.          break;
  1750.  
  1751.       case VK_F2:
  1752.          writestring( "VK_F2", outfile);
  1753.          break;
  1754.  
  1755.       case VK_F3:
  1756.          writestring( "VK_F3", outfile);
  1757.          break;
  1758.  
  1759.       case VK_F4:
  1760.          writestring( "VK_F4", outfile);
  1761.          break;
  1762.  
  1763.       case VK_F5:
  1764.          writestring( "VK_F5", outfile);
  1765.          break;
  1766.  
  1767.       case VK_F6:
  1768.          writestring( "VK_F6", outfile);
  1769.          break;
  1770.  
  1771.       case VK_F7:
  1772.          writestring( "VK_F7", outfile);
  1773.          break;
  1774.  
  1775.       case VK_F8:
  1776.          writestring( "VK_F8", outfile);
  1777.          break;
  1778.  
  1779.       case VK_F9:
  1780.          writestring( "VK_F9", outfile);
  1781.          break;
  1782.  
  1783.       case VK_F10:
  1784.          writestring( "VK_F10", outfile);
  1785.          break;
  1786.  
  1787.       case VK_F11:
  1788.          writestring( "VK_F11", outfile);
  1789.          break;
  1790.  
  1791.       case VK_F12:
  1792.          writestring( "VK_F12", outfile);
  1793.          break;
  1794.  
  1795.       case VK_F13:
  1796.          writestring( "VK_F13", outfile);
  1797.          break;
  1798.  
  1799.       case VK_F14:
  1800.          writestring( "VK_F14", outfile);
  1801.          break;
  1802.  
  1803.       case VK_F15:
  1804.          writestring( "VK_F15", outfile);
  1805.          break;
  1806.  
  1807.       case VK_F16:
  1808.          writestring( "VK_F16", outfile);
  1809.          break;
  1810.  
  1811.       case VK_F17:
  1812.          writestring( "VK_F17", outfile);
  1813.          break;
  1814.  
  1815.       case VK_F18:
  1816.          writestring( "VK_F18", outfile);
  1817.          break;
  1818.  
  1819.       case VK_F19:
  1820.          writestring( "VK_F19", outfile);
  1821.          break;
  1822.  
  1823.       case VK_F20:
  1824.          writestring( "VK_F20", outfile);
  1825.          break;
  1826.  
  1827.       case VK_F21:
  1828.          writestring( "VK_F21", outfile);
  1829.          break;
  1830.  
  1831.       case VK_F22:
  1832.          writestring( "VK_F22", outfile);
  1833.          break;
  1834.  
  1835.       case VK_F23:
  1836.          writestring( "VK_F23", outfile);
  1837.          break;
  1838.  
  1839.       case VK_F24:
  1840.          writestring( "VK_F24", outfile);
  1841.          break;
  1842.  
  1843.       case VK_NUMLOCK:
  1844.          writestring( "VK_NUMLOCK", outfile);
  1845.          break;
  1846.  
  1847.       case VK_SCROLL:
  1848.          writestring( "VK_SCROLL", outfile);
  1849.          break;
  1850.  
  1851.       default:
  1852.          write_word( wEvent, outfile);
  1853.          break;
  1854.  
  1855.     } /* switch(wEvent) - end */
  1856.  
  1857. } /* write_virtual_accel_event - end */
  1858.  
  1859.  
  1860. /***************************************************
  1861.   Write the character for the current accelerator
  1862. ****************************************************/
  1863. int write_accel_event( WORD wEvent, FILE *outfile) {
  1864.  
  1865.    if(((wEvent >= 65) && (wEvent <= 90)) ||
  1866.       ((wEvent >= 97) && (wEvent <= 122))) {
  1867.       write_char('"', outfile);
  1868.       write_char((BYTE) wEvent, outfile);
  1869.       write_char('"', outfile);
  1870.       return(0);
  1871.    }
  1872.  
  1873.    if((wEvent >= 1) && (wEvent <= 26)) {
  1874.       write_char('"', outfile);
  1875.       write_char('^', outfile);
  1876.       write_char((BYTE) (wEvent + 64), outfile);
  1877.       write_char('"', outfile);
  1878.       return(0);
  1879.    }
  1880.  
  1881.    write_word( wEvent, outfile);
  1882.    return(1);
  1883.  
  1884. } /* write_accel_event - end */
  1885.  
  1886.  
  1887. /***************************************************
  1888.   Write the flags for the current accelerator
  1889. ****************************************************/
  1890. void write_accel_flags( BYTE flags, FILE *outfile, int ascii_value_used) {
  1891.  
  1892.    if(flags & 0x02)
  1893.       writestring(", NOINVERT", outfile);
  1894.    if(flags & 0x04)
  1895.       writestring(", SHIFT", outfile);
  1896.    if(flags & 0x08)
  1897.       writestring(", CONTROL", outfile);
  1898.    if(flags & 0x10)
  1899.       writestring(", ALT", outfile);
  1900.    if(flags & 0x01)
  1901.       writestring(", VIRTKEY", outfile);
  1902.    else if (ascii_value_used)
  1903.       writestring(", ASCII", outfile);
  1904.    writeline("", outfile);
  1905.  
  1906. } /* write_accel_flags - end */
  1907.  
  1908.  
  1909. /***************************************************
  1910.   Process the accelerator resource
  1911. ****************************************************/
  1912. void process_accelerator(int restype, FILE *infile, FILE *outfile) {
  1913.  
  1914.    DWORD  reslen;
  1915.    struct AccelTableEntry accelhdr;
  1916.    int    ascii_value_used;
  1917.  
  1918.    write_resource_name(infile, outfile);
  1919.    write_char(' ', outfile);
  1920.    writestring(res_array[restype], outfile);
  1921.    get_mem_flags(infile);
  1922.    writeline(" {", outfile);
  1923.  
  1924.    increase_indent();
  1925.  
  1926.    reslen = get_resource_length(infile);
  1927.  
  1928.    while(reslen) {
  1929.  
  1930.       write_indent(outfile);
  1931.  
  1932.       fread(&accelhdr, sizeof(struct AccelTableEntry), 1, infile);
  1933.       reslen -= sizeof(struct AccelTableEntry);
  1934.  
  1935.       if(accelhdr.fFlags & 0x01)
  1936.          write_virtual_accel_event( accelhdr.wEvent, outfile);
  1937.       else
  1938.          ascii_value_used = write_accel_event( accelhdr.wEvent, outfile);
  1939.  
  1940.       writestring(", ", outfile);
  1941.       write_word(accelhdr.wId, outfile);
  1942.       write_accel_flags( accelhdr.fFlags, outfile, ascii_value_used);
  1943.  
  1944.    }
  1945.  
  1946.    decrease_indent();
  1947.  
  1948.    writeline("}", outfile);
  1949.  
  1950. } /* process_accelerator - end */
  1951.  
  1952.  
  1953. /***************************************************
  1954.   Process the rcdata resource
  1955. ****************************************************/
  1956. void process_rcdata(int restype, FILE *infile, FILE *outfile) {
  1957.  
  1958.    DWORD reslen;
  1959.    int ch;
  1960.    unsigned short ch_count;
  1961.  
  1962.    write_resource_name(infile, outfile);
  1963.    write_char(' ', outfile);
  1964.    writestring(res_array[restype], outfile);
  1965.    write_mem_flags(infile, outfile);
  1966.    writeline(" {", outfile);
  1967.  
  1968.    reslen = get_resource_length(infile);
  1969.    increase_indent();
  1970.  
  1971.    /* copy the data out to the .rc file */
  1972.    ch_count = 0;
  1973.    while (reslen--) {
  1974.       if (ch_count == 0) {
  1975.          write_indent(outfile);
  1976.          write_char('"', outfile);
  1977.       }
  1978.       ch = fgetc( infile );
  1979.       if ((ch >= 32) && (ch <= 126)) {
  1980.          fputc( ch, outfile);
  1981.          ++ch_count;
  1982.       }
  1983.       else {
  1984.          write_char('\\', outfile);
  1985.          fprintf( outfile, "%o", ch);
  1986.          ch_count += 4;
  1987.       }
  1988.       if (ch_count >= 60) {
  1989.          writeline("\"", outfile);
  1990.          ch_count = 0;
  1991.       }
  1992.    }
  1993.  
  1994.    /* if last string wasn't terminated with end quotes, do so now */
  1995.    if (ch_count > 0)
  1996.       writeline("\"", outfile);
  1997.  
  1998.    decrease_indent();
  1999.  
  2000.    writeline("}", outfile);
  2001.  
  2002. } /* process_rcdata - end */
  2003.  
  2004.  
  2005. /***************************************************
  2006.   Search infile for image #image_num of type image_type
  2007. ****************************************************/
  2008. int search_for_image( WORD image_num, FILE *infile, int image_type ) {
  2009.  
  2010.    BYTE ch;
  2011.    long reslen;
  2012.    int  restype;
  2013.    WORD dest_image_num;
  2014.  
  2015.    fseek(infile, 0, 0);
  2016.  
  2017.    ch = get_byte(infile);
  2018.    while(!feof(infile)) {
  2019.  
  2020.       /* get the resource type */
  2021.       if(ch == 0xFF) {
  2022.  
  2023.          fread(&restype, sizeof(int), 1, infile);
  2024.  
  2025.          /* If it's not the right image type, skip it */
  2026.          if (restype != image_type) {
  2027.             
  2028.             get_resource_name(infile);
  2029.             get_mem_flags(infile);
  2030.             reslen = get_resource_length(infile);
  2031.  
  2032.             fseek(infile, reslen, 1);
  2033.          }
  2034.          else {
  2035.             dest_image_num = get_resource_number(infile);
  2036.             get_mem_flags(infile);
  2037.             reslen = get_resource_length(infile);
  2038.  
  2039.             if (dest_image_num == image_num)
  2040.                return(1);
  2041.             else
  2042.                fseek(infile, reslen, 1);
  2043.          }
  2044.  
  2045.       }
  2046.       else {
  2047.  
  2048.          /* read the name of the resource */
  2049.          while((ch = get_byte(infile)) != 0x00) {}
  2050.  
  2051.          get_resource_name(infile);
  2052.          get_mem_flags(infile);
  2053.          reslen = get_resource_length(infile);
  2054.  
  2055.          fseek(infile, reslen, 1);
  2056.       }
  2057.  
  2058.       ch = get_byte(infile);
  2059.  
  2060.    } /* while(not eof(infile)) - end */
  2061.  
  2062.    return(0);
  2063.  
  2064. } /* search_for_image - end */
  2065.  
  2066.  
  2067. /***************************************************
  2068.   Write the Cursor Directory entry to the cursor file
  2069. ****************************************************/
  2070. void write_cursor_direntry( CURSORDIRENTRY cursorentry, FILE *datafile, 
  2071.                             FILE *infile, DWORD cursor_size) {
  2072.  
  2073.    CURSORRESENTRY cursorres;
  2074.    long filepos;
  2075.    WORD hotspot;
  2076.  
  2077.    cursorres.bWidth      = (BYTE) cursorentry.wWidth;
  2078.    cursorres.bHeight     = (BYTE) (cursorentry.wHeight - cursorentry.wWidth);
  2079.    cursorres.bColorCount = 0;
  2080.    cursorres.bReserved   = 0;
  2081.  
  2082.    /* Initialize to 0's */
  2083.    cursorres.wXHotSpot = 0;
  2084.    cursorres.wYHotSpot = 0;
  2085.  
  2086.    /* Save the current position of the input file */
  2087.    filepos = ftell(infile);
  2088.  
  2089.    /* Search for cursor resource number #wImageOffset to get the hotspots */
  2090.    if (search_for_image( cursorentry.wImageOffset, infile, CURSOR_TYPE)) {
  2091.       hotspot = get_word( infile );
  2092.       cursorres.wXHotSpot = hotspot;
  2093.  
  2094.       hotspot = get_word( infile );
  2095.       cursorres.wYHotSpot = hotspot;
  2096.    }
  2097.  
  2098.    /* return to the prior position in the input file */
  2099.    fseek(infile, filepos, 0);
  2100.  
  2101.    /* subtract size of 2 WORD values - X & Y Hot Spot - they occur */
  2102.    /* at the beginning of the cursor resource data, but really     */
  2103.    /* belong in the header, so they get subtracted from the length */
  2104.    cursorres.dwBytesInRes  = cursorentry.dwBytesInRes - (2 * sizeof(WORD));
  2105.  
  2106.    cursorres.dwImageOffset = cursor_size;
  2107.  
  2108.    fwrite( &cursorres, sizeof(CURSORRESENTRY), 1, datafile);
  2109.  
  2110. } /* write_cursor_direntry - end */
  2111.  
  2112.  
  2113. /***************************************************
  2114.   Process the group cursor resource
  2115. ****************************************************/
  2116. void process_group_cursor(FILE *infile, FILE *outfile) {
  2117.  
  2118.    DWORD reslen;
  2119.    char  datafilename[13];
  2120.    FILE  *datafile;
  2121.    long  CurrPos;
  2122.    DWORD cursor_size;
  2123.  
  2124.    CURSORHEADER   cursorinfo;
  2125.    CURSORDIRENTRY cursorentry;
  2126.    WORD count;
  2127.  
  2128.    write_resource_name(infile, outfile);
  2129.    writestring(" CURSOR", outfile);
  2130.  
  2131.    /* Now write out the memory flags for the previous resource */
  2132.    /* (cursor), since that has the correct value; this must be */
  2133.    /* done before the succeeding call to get_mem_flags, since  */
  2134.    /* that will change the value of prev_mem_flag.             */
  2135.    write_special_mem_flag_values( prev_mem_flag, outfile);
  2136.  
  2137.    /* Now skip over the memory flag for this resource */
  2138.    get_mem_flags(infile);
  2139.  
  2140.    write_char(' ', outfile);
  2141.  
  2142.    reslen = get_resource_length(infile);
  2143.  
  2144.    /* Determine a unique .cur filename in the current directory */
  2145.    strcpy(datafilename, get_data_filename("CU", "CUR"));
  2146.    if(strlen(datafilename) == 0) {
  2147.       writeline("<Unable to open output file>", outfile);
  2148.       fseek( infile, reslen, 1);
  2149.       return;
  2150.    }
  2151.  
  2152.    /* Write the name of the new cursor file to the .rc file */
  2153.    writeline( datafilename, outfile );
  2154.  
  2155.    /* open .cur output file */
  2156.    if((datafile = fopen(datafilename, "wb")) == NULL) {
  2157.       printf("Unable to open file %s\n", datafilename);
  2158.       fseek( infile, reslen, 1);
  2159.       return;
  2160.    }
  2161.  
  2162.    fread( &cursorinfo, sizeof(CURSORHEADER), 1, infile);
  2163.    fwrite( &cursorinfo, sizeof(CURSORHEADER), 1, datafile);
  2164.  
  2165.    cursor_size = sizeof(CURSORHEADER) + (sizeof(CURSORRESENTRY) * cursorinfo.cdCount);
  2166.    CurrPos = ftell(infile);
  2167.  
  2168.    /* Loop through each Cursor entry in the Group Cursor resource */
  2169.    count = cursorinfo.cdCount;
  2170.    while (count--) {
  2171.  
  2172.       /* Read the header for this cursor, and save to the output file */
  2173.       fread( &cursorentry, sizeof(CURSORDIRENTRY), 1, infile);
  2174.  
  2175.       write_cursor_direntry( cursorentry, datafile, infile, cursor_size);
  2176.       cursor_size += cursorentry.dwBytesInRes;
  2177.  
  2178.    }
  2179.  
  2180.    fseek(infile, CurrPos, 0);
  2181.  
  2182.    /* Loop through each Cursor entry in the Group Cursor resource */
  2183.    count = cursorinfo.cdCount;
  2184.    while (count--) {
  2185.  
  2186.       fread( &cursorentry, sizeof(CURSORDIRENTRY), 1, infile);
  2187.  
  2188.       CurrPos += sizeof(CURSORDIRENTRY);
  2189.  
  2190.       /* Search for cursor resource number #wImageOffset */
  2191.       if (search_for_image( cursorentry.wImageOffset, infile, CURSOR_TYPE)) {
  2192.  
  2193.          /* skip the 2 WORDS for XHotSpot and YHotSpot */
  2194.          fseek(infile, 4, 1);
  2195.  
  2196.          /* subtract the size of the 2 WORDs at the start: hotspot data */
  2197.          write_data( infile, datafile, 
  2198.                      (cursorentry.dwBytesInRes - (2 * sizeof(WORD))));
  2199.       }
  2200.  
  2201.       fseek(infile, CurrPos, 0);
  2202.  
  2203.    }
  2204.  
  2205.    fclose( datafile );
  2206.  
  2207. } /* process_group_cursor - end */
  2208.  
  2209.  
  2210. /***************************************************
  2211.   Write the Icon Directory entry to the icon file
  2212. ****************************************************/
  2213. void write_icon_direntry( ICONDIRENTRY iconentry, FILE *datafile, 
  2214.                           DWORD icon_size) {
  2215.  
  2216.    ICONRESENTRY iconres;
  2217.  
  2218.    iconres.bWidth        = iconentry.bWidth;
  2219.    iconres.bHeight       = iconentry.bHeight;
  2220.    iconres.bColorCount   = iconentry.bColorCount;
  2221.    iconres.bReserved     = iconentry.bReserved;
  2222.  
  2223. /* The Planes and BitCount values stored in the .ico file 
  2224.    seem to be ignored.
  2225.  
  2226.    iconres.wPlanes       = iconentry.wPlanes;
  2227.    iconres.wBitCount     = iconentry.wBitCount;
  2228.  
  2229. */
  2230.  
  2231.    iconres.wPlanes       = 0;
  2232.    iconres.wBitCount     = 0;
  2233.  
  2234.    iconres.dwBytesInRes  = iconentry.dwBytesInRes;
  2235.    iconres.dwImageOffset = icon_size;
  2236.  
  2237.    fwrite( &iconres, sizeof(ICONRESENTRY), 1, datafile);
  2238.  
  2239. } /* write_icon_direntry - end */
  2240.  
  2241.  
  2242. /***************************************************
  2243.   Process the group icon resource
  2244. ****************************************************/
  2245. void process_group_icon(FILE *infile, FILE *outfile) {
  2246.  
  2247.    DWORD reslen;
  2248.    char  datafilename[13];
  2249.    FILE  *datafile;
  2250.    long  CurrPos;
  2251.    DWORD icon_size;
  2252.  
  2253.    ICONHEADER   iconinfo;
  2254.    ICONDIRENTRY iconentry;
  2255.    WORD count;
  2256.  
  2257.    write_resource_name(infile, outfile);
  2258.    writestring(" ICON", outfile);
  2259.  
  2260.    /* Now write out the memory flags for the previous resource */
  2261.    /* (icon), since that has the correct value; this must be   */
  2262.    /* done before the succeeding call to get_mem_flags, since  */
  2263.    /* that will change the value of prev_mem_flag.             */
  2264.    write_special_mem_flag_values( prev_mem_flag, outfile);
  2265.  
  2266.    /* Now skip over the memory flag for this resource */
  2267.    get_mem_flags(infile);
  2268.  
  2269.    write_char(' ', outfile);
  2270.  
  2271.    reslen = get_resource_length(infile);
  2272.  
  2273.    /* Determine a unique .ico filename in the current directory */
  2274.    strcpy(datafilename, get_data_filename("IC", "ICO"));
  2275.    if(strlen(datafilename) == 0) {
  2276.       writeline("<Unable to open output file>", outfile);
  2277.       fseek( infile, reslen, 1);
  2278.       return;
  2279.    }
  2280.  
  2281.    /* Write the name of the new icon file to the .rc file */
  2282.    writeline( datafilename, outfile );
  2283.  
  2284.    /* Open the output file containing the icon resource data */
  2285.    if((datafile = fopen(datafilename, "wb")) == NULL) {
  2286.       printf("Unable to open file %s\n", datafilename);
  2287.       fseek( infile, reslen, 1);
  2288.       return;
  2289.    }
  2290.  
  2291.    fread( &iconinfo, sizeof(ICONHEADER), 1, infile);
  2292.    fwrite( &iconinfo, sizeof(ICONHEADER), 1, datafile);
  2293.  
  2294.    icon_size = sizeof(ICONHEADER) + (sizeof(ICONRESENTRY) * iconinfo.idCount);
  2295.    CurrPos = ftell(infile);
  2296.  
  2297.    /* Loop through each Icon entry in the Group Icon resource */
  2298.    count = iconinfo.idCount;
  2299.    while (count--) {
  2300.  
  2301.       fread( &iconentry, sizeof(ICONDIRENTRY), 1, infile);
  2302.  
  2303.       write_icon_direntry( iconentry, datafile, icon_size);
  2304.       icon_size += iconentry.dwBytesInRes;
  2305.  
  2306.    }
  2307.  
  2308.    fseek(infile, CurrPos, 0);
  2309.  
  2310.    /* Loop through each Icon entry in the Group Icon resource */
  2311.    count = iconinfo.idCount;
  2312.    while (count--) {
  2313.  
  2314.       fread( &iconentry, sizeof(ICONDIRENTRY), 1, infile);
  2315.  
  2316.       CurrPos += sizeof(ICONDIRENTRY);
  2317.  
  2318.       /* Search for icon resource number #wImageOffset */
  2319.       if (search_for_image( iconentry.wImageOffset, infile, ICON_TYPE)) {
  2320.          write_data( infile, datafile, iconentry.dwBytesInRes );
  2321.       }
  2322.  
  2323.       fseek(infile, CurrPos, 0);
  2324.  
  2325.    }
  2326.  
  2327.    fclose( datafile );
  2328.  
  2329. } /* process_group_icon - end */
  2330.  
  2331.  
  2332. /***************************************************
  2333.   Save a user-defined resource data to a file.
  2334. ****************************************************/
  2335. void save_user_resource( FILE *infile, FILE *outfile) {
  2336.  
  2337.    DWORD reslen;
  2338.    char  datafilename[13];
  2339.    FILE  *datafile;
  2340.  
  2341.    reslen = get_resource_length(infile);
  2342.  
  2343.    strcpy(datafilename, get_data_filename("UR", "USR"));
  2344.    if(strlen(datafilename) == 0) {
  2345.       writeline("<Unable to open output file>", outfile);
  2346.       fseek( infile, reslen, 1);
  2347.       return;
  2348.    }
  2349.  
  2350.    writeline( datafilename, outfile );
  2351.  
  2352.    if((datafile = fopen(datafilename, "wb")) == NULL) {
  2353.       printf("Unable to open file %s\n", datafilename);
  2354.       fseek( infile, reslen, 1);
  2355.       return;
  2356.    }
  2357.  
  2358.    write_data(infile, datafile, reslen);
  2359.    fclose( datafile );
  2360.  
  2361. } /* save_user_resource - end */
  2362.  
  2363.  
  2364. /***************************************************
  2365.   Process a user-defined resource (by number).
  2366. ****************************************************/
  2367. void process_user_resource_num(int restype, FILE *infile, FILE *outfile) {
  2368.  
  2369.    write_resource_name(infile, outfile);
  2370.    write_char(' ', outfile);
  2371.    write_number( restype, outfile);
  2372.    write_mem_flags(infile, outfile);
  2373.    write_char(' ', outfile);
  2374.  
  2375.    save_user_resource( infile, outfile );
  2376.  
  2377. } /* process_user_resource_num - end */
  2378.  
  2379.  
  2380. /***************************************************
  2381.   Read the name table, but ignore it.
  2382. ****************************************************/
  2383. void process_name_table( FILE *infile, FILE *outfile) {
  2384.  
  2385.    DWORD reslen;
  2386.  
  2387.    writeline( "", outfile);
  2388.    writeline( "//", outfile);
  2389.    writeline( "// Name table found, but ignored.", outfile );
  2390.    writeline( "//", outfile);
  2391.  
  2392.    get_resource_name(infile);
  2393.    get_mem_flags(infile);
  2394.  
  2395.    reslen = get_resource_length(infile);
  2396.    fseek(infile, reslen, 1);
  2397.  
  2398. } /* process_name_table - end */
  2399.  
  2400.  
  2401. /***************************************************
  2402.   Checks if ver.h has been included; if not, does so
  2403. ****************************************************/
  2404. void check_if_ver_header_included( FILE *outfile ) {
  2405.  
  2406.    if (VersionUsed == 0) {
  2407.  
  2408.       /* update VersionUsed so <ver.h> can't be included twice */
  2409.       VersionUsed = 1;
  2410.  
  2411.       writeline( "", outfile);
  2412.       writeline( "#include <ver.h>", outfile);
  2413.  
  2414.    }
  2415.  
  2416. } /* check_if_ver_header_included - end */
  2417.  
  2418.  
  2419. /***************************************************
  2420.   Process version fileflags
  2421. ****************************************************/
  2422. void write_version_fileflags( DWORD style, FILE *outfile ) {
  2423.  
  2424.    WORD first_style = 1;
  2425.    WORD line_len = 0;
  2426.  
  2427.    writestring( " FILEFLAGS ", outfile);
  2428.  
  2429.    if (style == 0L)
  2430.       writeline( "0x0L", outfile);
  2431.    else {
  2432.       check_for_dlg_style( VS_FF_DEBUG & style, &first_style,
  2433.                            &line_len, "VS_FF_DEBUG", outfile);
  2434.       check_for_dlg_style( VS_FF_INFOINFERRED & style, &first_style, 
  2435.                            &line_len, "VS_FF_INFOINFERRED", outfile);
  2436.       check_for_dlg_style( VS_FF_PATCHED & style, &first_style, 
  2437.                            &line_len, "VS_FF_PATCHED", outfile);
  2438.       check_for_dlg_style( VS_FF_PRERELEASE & style, &first_style, 
  2439.                            &line_len, "VS_FF_PRERELEASE", outfile);
  2440.       check_for_dlg_style( VS_FF_PRIVATEBUILD & style, &first_style, 
  2441.                            &line_len, "VS_FF_PRIVATEBUILD", outfile);
  2442.       check_for_dlg_style( VS_FF_SPECIALBUILD & style, &first_style, 
  2443.                            &line_len, "VS_FF_SPECIALBUILD", outfile);
  2444.  
  2445.       writeline( "", outfile);
  2446.    }
  2447.  
  2448. } /* write_version_fileflags - end */
  2449.  
  2450.  
  2451. /***************************************************
  2452.   Process the version driver subtype
  2453. ****************************************************/
  2454. void process_version_driver_subtype( DWORD driver_subtype, FILE *outfile ) {
  2455.  
  2456.    switch (driver_subtype) {
  2457.  
  2458.       case VFT2_UNKNOWN:
  2459.          writeline("VFT2_UNKNOWN", outfile);
  2460.          break;
  2461.  
  2462.       case VFT2_DRV_COMM:
  2463.          writeline("VFT2_DRV_COMM", outfile);
  2464.          break;
  2465.  
  2466.       case VFT2_DRV_PRINTER:
  2467.          writeline("VFT2_DRV_PRINTER", outfile);
  2468.          break;
  2469.  
  2470.       case VFT2_DRV_KEYBOARD:
  2471.          writeline("VFT2_DRV_KEYBOARD", outfile);
  2472.          break;
  2473.  
  2474.       case VFT2_DRV_LANGUAGE:
  2475.          writeline("VFT2_DRV_LANGUAGE", outfile);
  2476.          break;
  2477.  
  2478.       case VFT2_DRV_DISPLAY:
  2479.          writeline("VFT2_DRV_DISPLAY", outfile);
  2480.          break;
  2481.  
  2482.       case VFT2_DRV_MOUSE:
  2483.          writeline("VFT2_DRV_MOUSE", outfile);
  2484.          break;
  2485.  
  2486.       case VFT2_DRV_NETWORK:
  2487.          writeline("VFT2_DRV_NETWORK", outfile);
  2488.          break;
  2489.  
  2490.       case VFT2_DRV_SYSTEM:
  2491.          writeline("VFT2_DRV_SYSTEM", outfile);
  2492.          break;
  2493.  
  2494.       case VFT2_DRV_INSTALLABLE:
  2495.          writeline("VFT2_DRV_INSTALLABLE", outfile);
  2496.          break;
  2497.  
  2498.       case VFT2_DRV_SOUND:
  2499.          writeline("VFT2_DRV_SOUND", outfile);
  2500.          break;
  2501.  
  2502.       default:
  2503.          fprintf( outfile, "%lu", driver_subtype );
  2504.          writeline("", outfile);
  2505.          break;
  2506.  
  2507.    } /* switch (driver_subtype) - end */
  2508.  
  2509. } /* process_version_driver_subtype - end */
  2510.  
  2511.  
  2512. /***************************************************
  2513.   Process the version font subtype
  2514. ****************************************************/
  2515. void process_version_font_subtype( DWORD font_subtype, FILE *outfile ) {
  2516.  
  2517.    switch (font_subtype) {
  2518.  
  2519.       case VFT2_UNKNOWN:
  2520.          writeline("VFT2_UNKNOWN", outfile);
  2521.          break;
  2522.  
  2523.       case VFT2_FONT_RASTER:
  2524.          writeline("VFT2_FONT_RASTER", outfile);
  2525.          break;
  2526.  
  2527.       case VFT2_FONT_VECTOR:
  2528.          writeline("VFT2_FONT_VECTOR", outfile);
  2529.          break;
  2530.  
  2531.       case VFT2_FONT_TRUETYPE:
  2532.          writeline("VFT2_FONT_TRUETYPE", outfile);
  2533.          break;
  2534.  
  2535.       default:
  2536.          fprintf( outfile, "%lu", font_subtype );
  2537.          writeline("", outfile);
  2538.          break;
  2539.  
  2540.    } /* switch (font_subtype) - end */
  2541.  
  2542. } /* process_version_font_subtype - end */
  2543.  
  2544.  
  2545. /***************************************************
  2546.   Process version information root block
  2547. ****************************************************/
  2548. void process_version_root_block( FILE *infile, FILE *outfile) {
  2549.  
  2550.    VS_FIXEDFILEINFO infostruct;
  2551.  
  2552.    /* Process each field of the root block */
  2553.    fread( &infostruct, sizeof(VS_FIXEDFILEINFO), 1, infile);
  2554.  
  2555.    fprintf( outfile, " FILEVERSION %u,%u,%u,%u",
  2556.                HIWORD(infostruct.dwFileVersionMS),
  2557.                LOWORD(infostruct.dwFileVersionMS),
  2558.                HIWORD(infostruct.dwFileVersionLS),
  2559.                LOWORD(infostruct.dwFileVersionLS));
  2560.    writeline( "", outfile);
  2561.  
  2562.    fprintf( outfile, " PRODUCTVERSION %u,%u,%u,%u",
  2563.                HIWORD(infostruct.dwProductVersionMS),
  2564.                LOWORD(infostruct.dwProductVersionMS),
  2565.                HIWORD(infostruct.dwProductVersionLS),
  2566.                LOWORD(infostruct.dwProductVersionLS));
  2567.    writeline( "", outfile);
  2568.  
  2569.    write_version_fileflags( infostruct.dwFileFlags, outfile );
  2570.  
  2571.    if(infostruct.dwFileFlagsMask == VS_FFI_FILEFLAGSMASK)
  2572.       fprintf( outfile, " FILEFLAGSMASK VS_FFI_FILEFLAGSMASK");
  2573.    else
  2574.       fprintf( outfile, " FILEFLAGSMASK %lu", infostruct.dwFileFlagsMask);
  2575.    writeline( "", outfile);
  2576.  
  2577.    writestring( " FILEOS ", outfile);
  2578.    switch (infostruct.dwFileOS) {
  2579.  
  2580.       case VOS_UNKNOWN:
  2581.          writeline("VOS_UNKNOWN", outfile);
  2582.          break;
  2583.  
  2584.       case VOS_DOS:
  2585.          writeline("VOS_DOS", outfile);
  2586.          break;
  2587.  
  2588.       case VOS_OS216:
  2589.          writeline("VOS_OS216", outfile);
  2590.          break;
  2591.  
  2592.       case VOS_OS232:
  2593.          writeline("VOS_OS232", outfile);
  2594.          break;
  2595.  
  2596.       case VOS_NT:
  2597.          writeline("VOS_NT", outfile);
  2598.          break;
  2599.  
  2600.       case VOS_DOS_WINDOWS16:
  2601.          writeline("VOS_DOS_WINDOWS16", outfile);
  2602.          break;
  2603.  
  2604.       case VOS_DOS_WINDOWS32:
  2605.          writeline("VOS_DOS_WINDOWS32", outfile);
  2606.          break;
  2607.  
  2608.       case VOS_OS216_PM16:
  2609.          writeline("VOS_OS216_PM16", outfile);
  2610.          break;
  2611.  
  2612.       case VOS_OS232_PM32:
  2613.          writeline("VOS_OS232_PM32", outfile);
  2614.          break;
  2615.  
  2616.       case VOS_NT_WINDOWS32:
  2617.          writeline("VOS_NT_WINDOWS32", outfile);
  2618.          break;
  2619.  
  2620.       default:
  2621.          fprintf( outfile, "%lu", infostruct.dwFileOS );
  2622.          writeline("", outfile);
  2623.          break;
  2624.  
  2625.    } /* switch (FileOS) - end */
  2626.  
  2627.    writestring( " FILETYPE ", outfile);
  2628.    switch (infostruct.dwFileType) {
  2629.  
  2630.       case VFT_UNKNOWN:
  2631.          writeline("VFT_UNKNOWN", outfile);
  2632.          break;
  2633.  
  2634.       case VFT_APP:
  2635.          writeline("VFT_APP", outfile);
  2636.          break;
  2637.  
  2638.       case VFT_DLL:
  2639.          writeline("VFT_DLL", outfile);
  2640.          break;
  2641.  
  2642.       case VFT_DRV:
  2643.          writeline("VFT_DRV", outfile);
  2644.          break;
  2645.  
  2646.       case VFT_FONT:
  2647.          writeline("VFT_FONT", outfile);
  2648.          break;
  2649.  
  2650.       case VFT_VXD:
  2651.          writeline("VFT_VXD", outfile);
  2652.          break;
  2653.  
  2654.       case VFT_STATIC_LIB:
  2655.          writeline("VFT_STATIC_LIB", outfile);
  2656.          break;
  2657.  
  2658.       default:
  2659.          fprintf( outfile, "%lu", infostruct.dwFileType );
  2660.          writeline("", outfile);
  2661.          break;
  2662.  
  2663.    } /* switch (FileType) - end */
  2664.  
  2665.    writestring( " FILESUBTYPE ", outfile);
  2666.    switch (infostruct.dwFileType) {
  2667.  
  2668.       case VFT_DRV:
  2669.          process_version_driver_subtype( infostruct.dwFileSubtype, outfile);
  2670.          break;
  2671.  
  2672.       case VFT_FONT:
  2673.          process_version_font_subtype( infostruct.dwFileSubtype, outfile);
  2674.          break;
  2675.  
  2676.       default:
  2677.          fprintf( outfile, "%lu", infostruct.dwFileSubtype );
  2678.          writeline("", outfile);
  2679.          break;
  2680.  
  2681.    } /* switch (FileSubtype) - end */
  2682.  
  2683.  
  2684. } /* process_version_root_block - end */
  2685.  
  2686.  
  2687. /***************************************************
  2688.   Write out the name of the current block, and return
  2689.    whether it was string, variable or other type of
  2690.    block.
  2691. ****************************************************/
  2692. int write_block_name( FILE *infile, FILE *outfile ) {
  2693.  
  2694.    int  count=1;      /* record number of chars read */
  2695.    int  blocktype=0;  /* record which type of block it is */
  2696.    BYTE ch;
  2697.  
  2698.    ch = get_byte(infile);
  2699.    if (ch == 'S')
  2700.       blocktype = STRINGBLOCK;
  2701.    else if (ch == 'V')
  2702.       blocktype = VARBLOCK;
  2703.    else
  2704.       blocktype = OTHERBLOCK;
  2705.  
  2706.    while((!feof(infile)) && (ch != 0x00)) {
  2707.       ++count;
  2708.       write_char( ch, outfile);
  2709.       ch = get_byte(infile);
  2710.    }
  2711.  
  2712.    /* Ensure number of characters read is a multiple of 4.    */
  2713.    /* According to the MS documentation, this is the format.  */
  2714.    /* See "MS Windows 3.1 Programmer's Reference" Vol.4, p.99 */
  2715.    count = count % 4;
  2716.    count = (count > 0) ? (4 - count) : 0;
  2717.    while ((!feof(infile)) && (count > 0)) {
  2718.       ch = get_byte(infile);
  2719.       --count;
  2720.    }
  2721.  
  2722.    return(blocktype);
  2723.  
  2724. } /* write_block_name - end */
  2725.  
  2726.  
  2727. /***************************************************
  2728.   Write out the name of the current block, and return
  2729.    the total number of characters in the field.
  2730. ****************************************************/
  2731. WORD write_ver_field_name( FILE *infile, FILE *outfile ) {
  2732.  
  2733.    WORD count=1;      /* record number of chars read */
  2734.    WORD fieldsize=1;  /* record number of chars read */
  2735.    BYTE ch;
  2736.  
  2737.    ch = get_byte(infile);
  2738.  
  2739.    while((!feof(infile)) && (ch != 0x00)) {
  2740.       ++count;
  2741.       write_char( ch, outfile);
  2742.       ch = get_byte(infile);
  2743.    }
  2744.    fieldsize = count;
  2745.  
  2746.    /* Ensure number of characters read is a multiple of 4.    */
  2747.    /* According to the MS documentation, this is the format.  */
  2748.    /* See "MS Windows 3.1 Programmer's Reference" Vol.4, p.99 */
  2749.    count = count % 4;
  2750.    count = (count > 0) ? (4 - count) : 0;
  2751.    while ((!feof(infile)) && (count > 0)) {
  2752.       ++fieldsize;
  2753.       ch = get_byte(infile);
  2754.       --count;
  2755.    }
  2756.  
  2757.    return(fieldsize);
  2758.  
  2759. } /* write_ver_field_name - end */
  2760.  
  2761.  
  2762. /***************************************************
  2763.   Read "wordsize" # of bytes and write them to the   
  2764.    output file; these bytes are the second part of 
  2765.    the  'VALUE "---", "---"' line in a version info
  2766.    string block.  Return the number of bytes needed
  2767.    to align the string on a 32-bit boundary.
  2768. ****************************************************/
  2769. WORD write_ver_field_name_size_n( FILE *infile, FILE *outfile,
  2770.                                   WORD wordsize ) {
  2771.  
  2772.    WORD count=0;      /* record number of chars read */
  2773.    WORD diff=0;
  2774.    BYTE ch;
  2775.  
  2776.    while((!feof(infile)) && (count < wordsize)) {
  2777.       ++count;
  2778.       ch = get_byte(infile);
  2779.       write_char( ch, outfile);
  2780.    }
  2781.  
  2782.    /* Ensure number of characters read is a multiple of 4.    */
  2783.    /* According to the MS documentation, this is the format.  */
  2784.    /* See "MS Windows 3.1 Programmer's Reference" Vol.4, p.99 */
  2785.    count = count % 4;
  2786.    count = (count > 0) ? (4 - count) : 0;
  2787.    diff = count;
  2788.    while ((!feof(infile)) && (count > 0)) {
  2789.       ch = get_byte(infile);
  2790.       --count;
  2791.    }
  2792.  
  2793.    return(diff);
  2794.  
  2795. } /* write_ver_field_name_size_n - end */
  2796.  
  2797.  
  2798. /***************************************************
  2799.   Process a version string block
  2800. ****************************************************/
  2801. void process_version_string_block( WORD blocksize, FILE *infile, 
  2802.                                    FILE *outfile ) {
  2803.  
  2804.    WORD stringblocksize = 0;
  2805.    WORD subblocksize = 0;
  2806.    WORD subdatasize  = 0;
  2807.    WORD fieldsize = 0;
  2808.    WORD diff = 0;
  2809.  
  2810.    WORD totalblocksize = 0;  /* size so far of the entire block */
  2811.    WORD totalsubsize   = 0;  /* size so far of a subblock */
  2812.  
  2813.    /* add up: len(StringFileInfo\0) + sizeof(blocksize) +  */
  2814.    /* sizeof(datasize) (values already read in)         */
  2815.    totalblocksize = 16 + (2 * sizeof(WORD));
  2816.  
  2817.    while (totalblocksize < blocksize) {
  2818.  
  2819.       /* get the name of this entire string block */
  2820.       stringblocksize = get_word( infile );
  2821.       (void)get_word( infile );
  2822.       totalblocksize += stringblocksize;
  2823.  
  2824.       write_indent( outfile );
  2825.       writestring( "BLOCK \"", outfile);
  2826.       fieldsize = write_ver_field_name( infile, outfile );
  2827.       writeline( "\"", outfile);
  2828.  
  2829.       write_indent( outfile );
  2830.       writeline( "BEGIN", outfile);
  2831.  
  2832.       increase_indent();
  2833.  
  2834.       totalsubsize = fieldsize + (2 * sizeof(WORD)); 
  2835.       while (totalsubsize < stringblocksize) {
  2836.  
  2837.          subblocksize = get_word(infile);
  2838.          subdatasize  = get_word(infile);
  2839.  
  2840.          /* increment the byte counter by the size of the current block */
  2841.          totalsubsize += subblocksize;
  2842.  
  2843.          write_indent( outfile );
  2844.          writestring( "VALUE \"", outfile);
  2845.          (void)write_ver_field_name( infile, outfile );
  2846.          writestring( "\", \"", outfile);
  2847.  
  2848.          diff = write_ver_field_name_size_n( infile, outfile, subdatasize );
  2849.  
  2850.          totalsubsize += diff;
  2851.          totalblocksize += diff;
  2852.  
  2853.          writeline( "\"", outfile);
  2854.  
  2855.       } /* while (totalsubsize < stringblocksize) - end */
  2856.  
  2857.       decrease_indent();
  2858.       write_indent( outfile );
  2859.       writeline( "END", outfile);
  2860.  
  2861.    } /* while (totalblocksize < blocksize) - end */
  2862.  
  2863. } /* process_version_string_block - end */
  2864.  
  2865.  
  2866. /***************************************************
  2867.   Process a version variable block
  2868. ****************************************************/
  2869. void process_version_var_block( WORD blocksize, FILE *infile, 
  2870.                                 FILE *outfile ) {
  2871.  
  2872.    WORD subblocksize = 0;
  2873.    WORD subdatasize  = 0;
  2874.    WORD totalsize    = 0;
  2875.  
  2876.    WORD langid    = 0;
  2877.    WORD charsetid = 0;
  2878.  
  2879.    /* add up: len(VarFileInfo\0) + sizeof(blocksize) +  */
  2880.    /* sizeof(datasize) (values already read in)         */
  2881.    totalsize = 12 + (2 * sizeof(WORD));
  2882.  
  2883.    while (totalsize < blocksize) {
  2884.  
  2885.       subblocksize = get_word( infile );
  2886.       subdatasize  = get_word( infile );
  2887.  
  2888.       write_indent( outfile );
  2889.       writestring( "VALUE \"", outfile);
  2890.       (void)write_block_name( infile, outfile );
  2891.       writestring( "\", ", outfile);
  2892.  
  2893.       /* increment the byte counter by the size of the current block */
  2894.       totalsize += subblocksize;
  2895.  
  2896.       while (subdatasize) {
  2897.  
  2898.          langid = get_word( infile );
  2899.          charsetid = get_word( infile );
  2900.  
  2901.          fprintf( outfile, "0x%X, %d", langid, charsetid);
  2902.  
  2903.          /* take off the size of the 2 variables read above */
  2904.          subdatasize -= (2 * sizeof(WORD)); 
  2905.  
  2906.          /* if another entry after this one, write out a comma */
  2907.          if (subdatasize) {
  2908.             writeline( ",", outfile);
  2909.             write_indent( outfile );
  2910.          }
  2911.          else
  2912.             writeline( "", outfile);
  2913.  
  2914.       } /* while (subdatasize) - end */
  2915.  
  2916.    } /* while (totalsize < blocksize) - end */
  2917.  
  2918. } /* process_version_var_block - end */
  2919.  
  2920.  
  2921. /***************************************************
  2922.   Process an unknown type of version block
  2923. ****************************************************/
  2924. void process_version_other_block( WORD blocksize, long currpos,
  2925.                                   FILE *infile, FILE *outfile ) {
  2926.  
  2927.    long newPos = 0L;
  2928.  
  2929.    write_indent( outfile );
  2930.    writeline("// Unknown block type - skipping", outfile);
  2931.  
  2932.    newPos = currpos + ((long) blocksize);
  2933.    fseek( infile, newPos, 0);
  2934.  
  2935. } /* process_version_other_block - end */
  2936.  
  2937.  
  2938. /***************************************************
  2939.   Process a version block, which can be either a
  2940.    StringFileInfo or VarFileInfo block.
  2941. ****************************************************/
  2942. void process_version_block( FILE *infile, FILE *outfile ) {
  2943.  
  2944.    WORD blocksize = 0;   /* size of the next (complete) block */
  2945.  
  2946.    long currpos = 0L;    /* use in case the block type is unknown */
  2947.  
  2948.    int  block_type = 0;  /* mark block as StringFileInfo or VarStringInfo */
  2949.  
  2950.    INDENT = 0;           /* reset the amount of indentation */
  2951.  
  2952.    currpos = ftell(infile);
  2953.  
  2954.    blocksize = get_word(infile);
  2955.    (void) get_word(infile);     /* skip over the size of current dataset */
  2956.  
  2957.    increase_indent();
  2958.    write_indent( outfile );
  2959.  
  2960.    writestring( "BLOCK \"", outfile);
  2961.    block_type = write_block_name( infile, outfile );
  2962.    writeline( "\"", outfile);
  2963.  
  2964.    write_indent( outfile );
  2965.    writeline( "BEGIN", outfile);
  2966.  
  2967.    increase_indent();
  2968.  
  2969.    /* call the appropriate procedure for block_type */
  2970.    switch (block_type) {
  2971.  
  2972.       case STRINGBLOCK:
  2973.          process_version_string_block( blocksize, infile, outfile );
  2974.          break;
  2975.  
  2976.       case VARBLOCK:
  2977.          process_version_var_block( blocksize, infile, outfile );
  2978.          break;
  2979.  
  2980.       case OTHERBLOCK:
  2981.       default:
  2982.          process_version_other_block( blocksize, currpos, infile, outfile );
  2983.          break;
  2984.  
  2985.    } /* switch (block_type) - end */
  2986.  
  2987.    decrease_indent();
  2988.    write_indent( outfile );
  2989.  
  2990.    writeline( "END", outfile);
  2991.  
  2992.    decrease_indent();
  2993.  
  2994. } /* process_version_block - end */
  2995.  
  2996.  
  2997. /***************************************************
  2998.   Process version information
  2999. ****************************************************/
  3000. void process_version_info( FILE *infile, FILE *outfile) {
  3001.  
  3002.    DWORD reslen = 0L;     /* total size of version info     */
  3003.    DWORD endpos = 0L;     /* ftell() of end of version info */
  3004.    DWORD currpos = 0L;    /* current position in input file */
  3005.  
  3006.    /* see if "#include <ver.h>" has already been written */
  3007.    check_if_ver_header_included( outfile );
  3008.  
  3009.    /* start writing out the version information */
  3010.    write_version_number(infile, outfile);
  3011.    writeline( "VERSIONINFO", outfile);
  3012.  
  3013.    /* version info doesn't seem to use memory flags, so skip them */
  3014.    get_mem_flags(infile);
  3015.  
  3016.    reslen = get_resource_length(infile);
  3017.    currpos = ftell(infile);
  3018.    endpos = currpos + reslen;
  3019.  
  3020.    /* get the name and size of the root block - we can ignore */
  3021.    /* this because we know what it's going to be.             */
  3022.    (void)get_word(infile); /* cbBlock */
  3023.    (void)get_word(infile); /* cbValue */
  3024.  
  3025.    get_version_name(infile); /* szKey[] */
  3026.  
  3027.    process_version_root_block(infile, outfile);
  3028.  
  3029.    writeline( "BEGIN", outfile);
  3030.  
  3031.    /* now go through all of the remaining blocks */
  3032.    currpos = ftell(infile);
  3033.    while (currpos < endpos) {
  3034.  
  3035.       process_version_block( infile, outfile );
  3036.       currpos = ftell(infile);
  3037.  
  3038.    }
  3039.  
  3040.    writeline( "END", outfile);
  3041.  
  3042. } /* process_version_info - end */
  3043.  
  3044.  
  3045. /***************************************************
  3046.   Call the appropriate function for each resource type
  3047. ****************************************************/
  3048. void process_resource_by_number(FILE *infile, FILE *outfile) {
  3049.  
  3050.    int restype = 0;
  3051.  
  3052.    INDENT = 0;
  3053.    fread(&restype, sizeof(int), 1, infile);
  3054.  
  3055.    /* If we're in the middle of a string table, and the new resource */
  3056.    /* isn't a string table, finish it off */
  3057.    if ((restype != STRING_TYPE) && (StringCount)) {
  3058.       writeline("}", outfile);
  3059.       StringCount = 0;
  3060.    }
  3061.  
  3062.    switch(restype) {
  3063.       case RT_CURSOR:
  3064.          process_cursor( infile );
  3065.          break;
  3066.  
  3067.       case RT_BITMAP:
  3068.          process_bitmap(restype, infile, outfile);
  3069.          break;
  3070.  
  3071.       case RT_ICON:
  3072.          process_icon( infile );
  3073.          break;
  3074.  
  3075.       case RT_MENU:
  3076.          process_menu(restype, infile, outfile);
  3077.          break;
  3078.  
  3079.       case RT_DIALOG:
  3080.          process_dialog(restype, infile, outfile);
  3081.          break;
  3082.  
  3083.       case RT_STRING:
  3084.          process_string(restype, infile, outfile);
  3085.          break;
  3086.  
  3087.       case RT_FONTDIR:
  3088.          process_fontdir( infile );
  3089.          break;
  3090.  
  3091.       case RT_FONT:
  3092.          process_font(restype, infile, outfile);
  3093.          break;
  3094.  
  3095.       case RT_ACCELERATOR:
  3096.          process_accelerator(restype, infile, outfile);
  3097.          break;
  3098.  
  3099.       case RT_RCDATA:
  3100.          process_rcdata(restype, infile, outfile);
  3101.          break;
  3102.  
  3103.       case RT_GROUP_CURSOR:
  3104.          process_group_cursor(infile, outfile);
  3105.          break;
  3106.  
  3107.       case RT_GROUP_ICON:
  3108.          process_group_icon(infile, outfile);
  3109.          break;
  3110.  
  3111.       /* name tables aren't used in Win3.1, so no predefined "RT_????" */
  3112.       case 15:
  3113.          process_name_table(infile, outfile);
  3114.          break;
  3115.  
  3116.       /* there doesn't seem to be an RT_????? for version info */
  3117.       case 16:
  3118.          process_version_info( infile, outfile);
  3119.          break;
  3120.  
  3121.       default:
  3122.          process_user_resource_num(restype, infile, outfile);
  3123.          break;
  3124.    
  3125.     }
  3126.  
  3127. } /* process_resource_by_number - end */
  3128.  
  3129.  
  3130. /***************************************************
  3131.    Process user-defined resource (by name)
  3132. ****************************************************/
  3133. void process_resource_by_name( BYTE ch, FILE *infile, FILE *outfile) {
  3134.  
  3135.    long  typeid_pos;  /* file position of type id */
  3136.    long  nameid_pos;  /* file position of name id */
  3137.  
  3138.    typeid_pos = ftell(infile);
  3139.  
  3140.    /* Skip the resource name */
  3141.    fseek( infile, -1, 1);
  3142.    get_resource_name(infile);
  3143.  
  3144.    /* Get the name of the resource itself */
  3145.    write_resource_name(infile, outfile);
  3146.    nameid_pos = ftell(infile);
  3147.  
  3148.    write_char(' ', outfile);
  3149.  
  3150.    /* now go back to the resource name and print it out */
  3151.    fseek( infile, typeid_pos, 0);
  3152.    get_custom_type( ch, infile, outfile );
  3153.  
  3154.    fseek( infile, nameid_pos, 0);
  3155.    write_mem_flags(infile, outfile);
  3156.    write_char(' ', outfile);
  3157.  
  3158.    save_user_resource( infile, outfile );
  3159.  
  3160. } /* process_resource_by_name - end */
  3161.  
  3162.  
  3163. /***************************************************
  3164.    Check the parameters passed on program invokation
  3165. ****************************************************/
  3166. void check_usage(int argc) {
  3167.  
  3168.    if (argc != 3) {
  3169.       printf("Usage: res2rc <.res filename> <.rc output filename>\n");
  3170.       exit(1);
  3171.    }
  3172.  
  3173. } /* check_usage - end */
  3174.  
  3175.  
  3176. /***************************************************
  3177.    Write the header to the output file.
  3178. ****************************************************/
  3179. void write_header( char *infname, char *outfname, FILE *outfile ) {
  3180.  
  3181.    writeline( "//", outfile);
  3182.    writestring( "// ", outfile);
  3183.    writestring( outfname, outfile);
  3184.    writestring( " - resource file decompiled from ", outfile);
  3185.    writeline( infname, outfile);
  3186.    writeline( "//", outfile);
  3187.    writeline( "#include <windows.h>", outfile);
  3188.  
  3189. } /* write_header - end */
  3190.  
  3191.  
  3192. /***************************************************
  3193.    Check if input file is a Win32 resource file
  3194. ****************************************************/
  3195. void check_for_win32_res( FILE *infile ) {
  3196.  
  3197.    char ch;
  3198.  
  3199.    ch = get_byte(infile);
  3200.    if(ch == 0x00) {
  3201.       printf("Input file is a Win32 .res file.  Stopping.\n");
  3202.       exit(1);
  3203.    }
  3204.    rewind(infile);
  3205.  
  3206. } /* check_for_win32_res - end */
  3207.  
  3208.  
  3209. /***************************************************
  3210.    Read .res file and process each resource.
  3211. ****************************************************/
  3212. int main(int argc, char *argv[]) {
  3213.  
  3214.    FILE *infile;
  3215.    FILE *outfile;
  3216.    BYTE ch;
  3217.  
  3218.    check_usage(argc);
  3219.  
  3220.    if((infile = fopen(argv[1], "rb")) == NULL) {
  3221.       printf("Error: Unable to open input file.\nStopping.\n");
  3222.       exit(1);
  3223.    }
  3224.  
  3225.    check_for_win32_res( infile );
  3226.  
  3227.    if((outfile = fopen(argv[2], "wb")) == NULL) {
  3228.       printf("Error: Unable to open output file.\nStopping.\n");
  3229.       exit(1);
  3230.    }
  3231.  
  3232.    write_header( argv[1], argv[2], outfile );
  3233.  
  3234.    StringCount   = 0;
  3235.  
  3236.    ch = get_byte(infile);
  3237.  
  3238.    while(!feof(infile)) {
  3239.  
  3240.       /* get the resource type */
  3241.       if(ch == 0xFF)
  3242.          process_resource_by_number(infile, outfile);
  3243.       else
  3244.          process_resource_by_name(ch, infile, outfile);
  3245.  
  3246.       ch = get_byte(infile);
  3247.  
  3248.    } /* while(not eof(infile)) - end */
  3249.  
  3250.    finish_off_stringtable(outfile);
  3251.  
  3252.    fclose(infile);
  3253.  
  3254.    return(0);
  3255.  
  3256. } /* main - end */
  3257.  
  3258. /* Res2Rc.c - end */
  3259.  
  3260.